📄 wxskinnableframe.cpp
字号:
/* * Roadnav * wxSkinnableFrame.cpp * * Copyright (c) 2004 - 2006 Richard L. Lynch <rllynch@users.sourceforge.net> * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ ///////////////////////////////////////////////////////////////////////////////// \file////// Contains the wxSkinnableFrame class and its support code - easily /// converts a regular frame into a skinnable one./////////////////////////////////////////////////////////////////////////////////#ifdef HAVE_CONFIG_H# include <config.h>#endif#ifdef _MSC_VER#pragma warning(disable: 4786)#pragma warning(disable: 4800)#endif#ifdef HAVE_STDIO_H#include <stdio.h>#endif#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#include <wx/wx.h>#include <wx/filename.h>#include "wxSkinnableFrame.h"#include "libroadnav/MapRepresentations.h"#include "libroadnav/MapSupport.h"#include "wxBitmapButtonNoBackground.h"#include "wxBitmapControl.h"#include <vector>using namespace std;//////////////////////////////////////////////////////////////////////////////////// \brief Make a vector of the names of the skins in the strDir directory./////////////////////////////////////////////////////////////////////////////////vector<wxString> EnumerateSkinsOneDir(wxString strDir){ vector<wxString> vRtn; wxFileName fnWildcard; wxString strFile; fnWildcard.AssignDir(strDir); fnWildcard.AppendDir(wxT("skins")); char szTmp[256]; strcpy(szTmp, fnWildcard.GetFullPath().mb_str(*wxConvCurrent)); if (!fnWildcard.DirExists()) return vRtn; fnWildcard.SetFullName(wxT("*")); strFile = wxFindFirstFile(fnWildcard.GetFullPath(), wxDIR); while (!strFile.IsEmpty() ) { wxFileName fnThis = strFile; vRtn.push_back(fnThis.GetName()); strFile = wxFindNextFile(); } return vRtn;}//////////////////////////////////////////////////////////////////////////////////// \brief Make a vector of the names of the skins in the common and user/// directory./////////////////////////////////////////////////////////////////////////////////vector<wxString> EnumerateSkins(){ vector<wxString> vRtn; vector<wxString> vTmp; vector<wxString>::iterator i; vRtn = EnumerateSkinsOneDir(GetCommonDataPath()); vTmp = EnumerateSkinsOneDir(GetLocalDataPath()); for (i = vTmp.begin(); i != vTmp.end(); i++) vRtn.push_back(*i); return vRtn;}//////////////////////////////////////////////////////////////////////////////////// \brief Map a skin name to its location./////////////////////////////////////////////////////////////////////////////////wxString ResolveSkinPath(wxString strName){ wxFileName fn; fn = strName; if (fn.DirExists()) return strName; fn.AssignDir(GetCommonDataPath()); fn.AppendDir(wxT("skins")); fn.AppendDir(strName); if (fn.DirExists()) return fn.GetFullPath(); fn.AssignDir(GetLocalDataPath()); fn.AppendDir(wxT("skins")); fn.AppendDir(strName); if (fn.DirExists()) return fn.GetFullPath(); return wxT("");}//////////////////////////////////////////////////////////////////////////////////// \brief Determine the amount of a space a multiline string would take up/// on a certain device context.////// strText is the text whose size is being measured////// dc is the device context////// w and h return the width and height of strText on the dc device context/////////////////////////////////////////////////////////////////////////////////void GetTextExtentMultiline(wxDC * dc, wxString strText, wxCoord * w, wxCoord * h){ wxString strLine; vector<wxString> vLines; int x, y; int iLineHeight; unsigned int iLine; *w = 0; *h = 0; if (strText == wxT("")) return; strLine = strText.BeforeFirst('\n'); strText = strText.AfterFirst('\n'); while (strLine != wxT("")) { vLines.push_back(strLine); strLine = strText.BeforeFirst('\n'); strText = strText.AfterFirst('\n'); } iLineHeight = 0; for (iLine = 0; iLine < vLines.size(); iLine++) { dc->GetTextExtent(vLines[iLine], &x, &y); if (x > *w) *w = x; if (y > iLineHeight) iLineHeight = y; } *h = iLineHeight * vLines.size();}//////////////////////////////////////////////////////////////////////////////////// \brief Loads a font from an XML element/////////////////////////////////////////////////////////////////////////////////wxFont LoadFont(TiXmlElement * root){ int iDefaultFontSize = -1; wxString strDefaultFontName; wxFont fntRtn; TiXmlElement * element; element = root->FirstChildElement(); while (element) { const char * pszName = element->Value(); const char * pszContents = NULL; TiXmlNode * node; for (node = element->FirstChild(); node && node->Type() != TiXmlNode::TEXT; node = node->NextSibling()); if (node) pszContents = node->Value(); if (!strcmp(pszName, "size") && pszContents) iDefaultFontSize = atoi(pszContents); if (!strcmp(pszName, "name") && pszContents) strDefaultFontName = wxString(pszContents, *wxConvCurrent); element = element->NextSiblingElement(); } fntRtn = *wxNORMAL_FONT; if (strDefaultFontName != wxT("")) fntRtn.SetFaceName(strDefaultFontName); if (iDefaultFontSize > 0) fntRtn.SetPointSize(iDefaultFontSize); return fntRtn;}//////////////////////////////////////////////////////////////////////////////////// \brief wxSkinnableFrame_ProportionalCoordinate constructor - initialize everything to zero/////////////////////////////////////////////////////////////////////////////////wxSkinnableFrame_ProportionalCoordinate::wxSkinnableFrame_ProportionalCoordinate(){ m_fMultiplier = 0; m_iOffset1 = 0; m_iOffset2 = 0;}//////////////////////////////////////////////////////////////////////////////////// \brief Loads a proportional position from an XML element/////////////////////////////////////////////////////////////////////////////////void wxSkinnableFrame_ProportionalCoordinate::Load(TiXmlElement * root){ root->QueryIntAttribute("offset1", &m_iOffset1); root->QueryIntAttribute("offset2", &m_iOffset2); root->QueryDoubleAttribute("multiplier", &m_fMultiplier);}//////////////////////////////////////////////////////////////////////////////////// \brief Loads a pair of coordinates from an XML element/////////////////////////////////////////////////////////////////////////////////void wxSkinnableFrame_ProportionalPoint::Load(TiXmlElement * root){ TiXmlElement * element; element = root->FirstChildElement("x"); if (!element) return; m_cX.Load(element); element = root->FirstChildElement("y"); if (!element) return; m_cY.Load(element); return;}//////////////////////////////////////////////////////////////////////////////////// \brief Resolve this coordinate given the size of the control/////////////////////////////////////////////////////////////////////////////////int wxSkinnableFrame_ProportionalCoordinate::Resolve(int iMax){ return (int) (m_iOffset1 + (m_iOffset2 + iMax) * m_fMultiplier);}//////////////////////////////////////////////////////////////////////////////////// \brief Resolve this point given the size of the control/////////////////////////////////////////////////////////////////////////////////wxPoint wxSkinnableFrame_ProportionalPoint::Resolve(wxPoint cMax){ return wxPoint(m_cX.Resolve(cMax.x), m_cY.Resolve(cMax.y));}//////////////////////////////////////////////////////////////////////////////////// \brief wxSkinnableFrame_LayoutControl constructor/////////////////////////////////////////////////////////////////////////////////wxSkinnableFrame_LayoutControl::wxSkinnableFrame_LayoutControl(){ m_cCenterWidth = -1; m_iShowMinHeight = 0; m_iShowMinWidth = 0;}//////////////////////////////////////////////////////////////////////////////////// \brief Position this control according to m_coTopLeft and m_coBottomRight/////////////////////////////////////////////////////////////////////////////////void wxSkinnableFrame_LayoutControl::Position(wxSize szParent, wxSize szParentWnd){ wxPoint ptTopLeft; wxPoint ptBottomRight; bool bWantVisible; ptTopLeft = m_coTopLeft.Resolve(wxPoint(szParent.x, szParent.y)); ptBottomRight = m_coBottomRight.Resolve(wxPoint(szParent.x, szParent.y)); if (ptTopLeft.x >= szParent.x) ptTopLeft.x = szParent.x - 1; if (ptTopLeft.y >= szParent.y) ptTopLeft.y = szParent.y - 1; if (ptBottomRight.x >= szParent.x) ptBottomRight.x = szParent.x - 1; if (ptBottomRight.y >= szParent.y) ptBottomRight.y = szParent.y - 1; if (m_cCenterWidth >= 0) { ptTopLeft.x = (ptBottomRight.x + ptTopLeft.x) / 2 - m_cCenterWidth / 2; ptBottomRight.x = (ptBottomRight.x + ptTopLeft.x) / 2 + m_cCenterWidth / 2 + 5; } m_pControl->SetSize(ptTopLeft.x, ptTopLeft.y, ptBottomRight.x - ptTopLeft.x, ptBottomRight.y - ptTopLeft.y); bWantVisible = true; if (szParentWnd.y < m_iShowMinHeight || szParentWnd.x < m_iShowMinWidth) bWantVisible = false; if (m_pControl->IsShown() != bWantVisible) m_pControl->Show(bWantVisible);}//////////////////////////////////////////////////////////////////////////////////// \brief Event table for wxSkinnableTable/////////////////////////////////////////////////////////////////////////////////BEGIN_EVENT_TABLE(wxSkinnableFrame, wxFrame) EVT_SIZE(wxSkinnableFrame::OnSize) EVT_TIMER(TIMER_REFRESH, wxSkinnableFrame::OnTimerRefresh)END_EVENT_TABLE()using namespace std;//////////////////////////////////////////////////////////////////////////////////// \brief wxSkinnableFrame constructor - just calls base constructor/////////////////////////////////////////////////////////////////////////////////wxSkinnableFrame::wxSkinnableFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxFrame(parent, id, title, pos, size, style, name){ m_pTimerRefresh = new wxTimer(this, TIMER_REFRESH);}wxSkinnableFrame::~wxSkinnableFrame(){ delete m_pTimerRefresh;}//////////////////////////////////////////////////////////////////////////////////// \brief Given a filename to a skin data file, generate a complete pathname/////////////////////////////////////////////////////////////////////////////////wxString wxSkinnableFrame::GetDataFilename(wxString strName){ wxFileName fn; fn.AssignDir(m_strSkinPath); fn.SetFullName(strName); return fn.GetFullPath();}//////////////////////////////////////////////////////////////////////////////////// \brief Load attributes from an XML element that are common to all of the/// controls like its region, foreground/background color, etc./////////////////////////////////////////////////////////////////////////////////bool wxSkinnableFrame::ApplyControlCommonAttributes(TiXmlElement * root, wxSkinnableFrame_LayoutControl * psLayoutControl, wxControl * pControl){ TiXmlElement * element; TiXmlElement * child; const char * pszTmp; element = root->FirstChildElement("region"); if (!element) return true; // top left child = element->FirstChildElement("topleft"); if (!child) return true; psLayoutControl->m_coTopLeft.Load(child); // bottom right child = element->FirstChildElement("bottomright"); if (!child) return true; psLayoutControl->m_coBottomRight.Load(child); // font child = root->FirstChildElement("font"); if (child) { wxFont fntThis = LoadFont(child); pControl->SetFont(fntThis); } pszTmp = root->Attribute("bgcolor"); if (pszTmp) pControl->SetBackgroundColour(ParseColor(wxString(pszTmp, *wxConvCurrent))); pszTmp = root->Attribute("fgcolor"); if (pszTmp) pControl->SetForegroundColour(ParseColor(wxString(pszTmp, *wxConvCurrent))); pszTmp = root->Attribute("showminheight"); if (pszTmp) psLayoutControl->m_iShowMinHeight = atoi(pszTmp); pszTmp = root->Attribute("showminwidth"); if (pszTmp) psLayoutControl->m_iShowMinWidth = atoi(pszTmp); return false;}//////////////////////////////////////////////////////////////////////////////////// \brief Process the control element in layout/////////////////////////////////////////////////////////////////////////////////bool wxSkinnableFrame::LoadSkinLayoutControl(TiXmlElement * root){ const char * pszAttributeName; wxSkinnableFrame_LayoutControl sLayoutControl; // name pszAttributeName = root->Attribute("name"); if (!pszAttributeName) return true; // request the derived class create the control now
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -