#include "wx/dcmemory.h"
#include "wx/window.h"
+ #include "wx/menu.h"
+
#include "wx/bmpbuttn.h"
#include "wx/button.h"
#include "wx/checkbox.h"
#include "wx/slider.h"
#include "wx/textctrl.h"
#include "wx/toolbar.h"
+
+ #include "wx/settings.h"
#endif // WX_PRECOMP
#include "wx/notebook.h"
#include "wx/spinbutt.h"
+#include "wx/toplevel.h"
+#include "wx/artprov.h"
#include "wx/univ/renderer.h"
#include "wx/univ/inphand.h"
#include "wx/univ/colschem.h"
#include "wx/univ/theme.h"
-#include "wx/toplevel.h"
+
+class WXDLLEXPORT wxGTKMenuGeometryInfo;
// ----------------------------------------------------------------------------
// constants (to be removed, for testing only)
virtual void DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect,
- int flags = 0);
+ int flags = 0,
+ wxWindow *window = NULL );
virtual void DrawLabel(wxDC& dc,
const wxString& label,
const wxRect& rect,
virtual wxSize GetFrameMinSize(int flags) const;
virtual wxSize GetFrameIconSize() const;
virtual int HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const;
-
- virtual wxIcon GetStdIcon(int which) const;
virtual void GetComboBitmaps(wxBitmap *bmpNormal,
wxBitmap *bmpFocus,
// draw the background with any colour, not only the default one(s)
void DoDrawBackground(wxDC& dc,
const wxColour& col,
- const wxRect& rect);
+ const wxRect& rect,
+ wxWindow *window = NULL);
// DrawBorder() helpers: all of them shift and clip the DC after drawing
// the border
wxAlignment align,
int indexAccel);
+ // common part of DrawMenuItem() and DrawMenuBarItem()
+ void DoDrawMenuItem(wxDC& dc,
+ const wxRect& rect,
+ const wxString& label,
+ int flags,
+ int indexAccel,
+ const wxString& accel = _T(""),
+ const wxBitmap& bitmap = wxNullBitmap,
+ const wxGTKMenuGeometryInfo *geometryInfo = NULL);
+
// initialize the combo bitmaps
void InitComboBitmaps();
virtual wxColour GetBackground(wxWindow *win) const;
};
+// ----------------------------------------------------------------------------
+// wxGTKArtProvider
+// ----------------------------------------------------------------------------
+
+class wxGTKArtProvider : public wxArtProvider
+{
+protected:
+ virtual wxBitmap CreateBitmap(const wxArtID& id,
+ const wxArtClient& client,
+ const wxSize& size);
+};
+
// ----------------------------------------------------------------------------
// wxGTKTheme
// ----------------------------------------------------------------------------
virtual ~wxGTKTheme();
virtual wxRenderer *GetRenderer();
+ virtual wxArtProvider *GetArtProvider();
virtual wxInputHandler *GetInputHandler(const wxString& control);
virtual wxColourScheme *GetColourScheme();
wxGTKRenderer *m_renderer;
+ wxGTKArtProvider *m_artProvider;
+
// the names of the already created handlers and the handlers themselves
// (these arrays are synchronized)
wxSortedArrayString m_handlerNames;
m_scheme = NULL;
m_renderer = NULL;
m_handlerDefault = NULL;
+ m_artProvider = NULL;
}
wxGTKTheme::~wxGTKTheme()
delete m_handlerDefault;
delete m_renderer;
delete m_scheme;
+ wxArtProvider::RemoveProvider(m_artProvider);
}
wxRenderer *wxGTKTheme::GetRenderer()
return m_renderer;
}
+wxArtProvider *wxGTKTheme::GetArtProvider()
+{
+ if ( !m_artProvider )
+ {
+ m_artProvider = new wxGTKArtProvider;
+ }
+
+ return m_artProvider;
+}
+
wxColourScheme *wxGTKTheme::GetColourScheme()
{
if ( !m_scheme )
dc.DrawLabel(label, rectShadow, alignment, indexAccel);
dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, CONTROL_TEXT_DISABLED));
}
+ else
+ {
+ dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, CONTROL_TEXT));
+ }
dc.DrawLabel(label, image, rect, alignment, indexAccel, rectBounds);
}
wxRect rectBitmap = rect;
rectBitmap.x -= 1;
rectBitmap.width = GetCheckBitmapSize().x;
+
// never draw the focus rect around the check indicators here
DrawCheckButton(dc, _T(""), bitmap, rectBitmap, flags & ~wxCONTROL_FOCUSED);
wxRect rectLabel = rect;
- wxCoord shift = rectBitmap.width + 2*GetCheckItemMargin();
+ wxCoord shift = rectBitmap.width + 2*GetCheckItemMargin();
rectLabel.x += shift;
rectLabel.width -= shift;
DrawItem(dc, label, rectLabel, flags);
if ( flags & wxCONTROL_PRESSED )
{
- DrawBorder(dc, wxBORDER_SUNKEN, rect, flags);
+ DrawBorder(dc, wxBORDER_SUNKEN, rect, flags, &rect);
+
+ DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_PRESSED), rect);
}
else if ( flags & wxCONTROL_CURRENT )
{
- DrawBorder(dc, wxBORDER_RAISED, rect, flags);
+ DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rect);
+
+ DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rect);
}
dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
// menu and menubar
// ----------------------------------------------------------------------------
+// wxGTKMenuGeometryInfo: the wxMenuGeometryInfo used by wxGTKRenderer
+class WXDLLEXPORT wxGTKMenuGeometryInfo : public wxMenuGeometryInfo
+{
+public:
+ virtual wxSize GetSize() const { return m_size; }
+
+ wxCoord GetLabelOffset() const { return m_ofsLabel; }
+ wxCoord GetAccelOffset() const { return m_ofsAccel; }
+
+ wxCoord GetItemHeight() const { return m_heightItem; }
+
+private:
+ // the total size of the menu
+ wxSize m_size;
+
+ // the offset of the start of the menu item label
+ wxCoord m_ofsLabel;
+
+ // the offset of the start of the accel label
+ wxCoord m_ofsAccel;
+
+ // the height of a normal (not separator) item
+ wxCoord m_heightItem;
+
+ friend wxMenuGeometryInfo *
+ wxGTKRenderer::GetMenuGeometry(wxWindow *, const wxMenu&) const;
+};
+
+// FIXME: all constants are hardcoded but shouldn't be
+static const wxCoord MENU_LEFT_MARGIN = 9;
+static const wxCoord MENU_RIGHT_MARGIN = 6;
+
+static const wxCoord MENU_HORZ_MARGIN = 6;
+static const wxCoord MENU_VERT_MARGIN = 3;
+
+// the margin around bitmap/check marks (on each side)
+static const wxCoord MENU_BMP_MARGIN = 2;
+
+// the margin between the labels and accel strings
+static const wxCoord MENU_ACCEL_MARGIN = 8;
+
+// the separator height in pixels: in fact, strangely enough, the real height
+// is 2 but Windows adds one extra pixel in the bottom margin, so take it into
+// account here
+static const wxCoord MENU_SEPARATOR_HEIGHT = 3;
+
+// the size of the standard checkmark bitmap
+static const wxCoord MENU_CHECK_SIZE = 9;
+
void wxGTKRenderer::DrawMenuBarItem(wxDC& dc,
const wxRect& rect,
const wxString& label,
int flags,
int indexAccel)
{
- DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE, indexAccel);
+ DoDrawMenuItem(dc, rect, label, flags, indexAccel);
}
void wxGTKRenderer::DrawMenuItem(wxDC& dc,
wxCoord y,
- const wxMenuGeometryInfo& geometryInfo,
+ const wxMenuGeometryInfo& gi,
const wxString& label,
const wxString& accel,
const wxBitmap& bitmap,
int flags,
int indexAccel)
{
- wxFAIL_MSG(_T("TODO"));
+ const wxGTKMenuGeometryInfo& geomInfo = (const wxGTKMenuGeometryInfo&)gi;
+
+ wxRect rect;
+ rect.x = 0;
+ rect.y = y;
+ rect.width = geomInfo.GetSize().x;
+ rect.height = geomInfo.GetItemHeight();
+
+ DoDrawMenuItem(dc, rect, label, flags, indexAccel, accel, bitmap, &geomInfo);
+}
+
+void wxGTKRenderer::DoDrawMenuItem(wxDC& dc,
+ const wxRect& rectOrig,
+ const wxString& label,
+ int flags,
+ int indexAccel,
+ const wxString& accel,
+ const wxBitmap& bitmap,
+ const wxGTKMenuGeometryInfo *geometryInfo)
+{
+ wxRect rect = rectOrig;
+
+ // draw the selected item specially
+ if ( flags & wxCONTROL_SELECTED )
+ {
+ wxRect rectIn;
+ DrawBorder(dc, wxBORDER_RAISED, rect, flags, &rectIn);
+
+ DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL_CURRENT), rectIn);
+ }
+
+ rect.Deflate(MENU_HORZ_MARGIN, MENU_VERT_MARGIN);
+
+ // draw the bitmap: use the bitmap provided or the standard checkmark for
+ // the checkable items
+ if ( geometryInfo )
+ {
+ wxBitmap bmp = bitmap;
+ if ( !bmp.Ok() && (flags & wxCONTROL_CHECKABLE) )
+ {
+ bmp = GetCheckBitmap(flags);
+ }
+
+ if ( bmp.Ok() )
+ {
+ rect.SetRight(geometryInfo->GetLabelOffset());
+ wxControlRenderer::DrawBitmap(dc, bmp, rect);
+ }
+ }
+ //else: menubar items don't have bitmaps
+
+ // draw the label
+ if ( geometryInfo )
+ {
+ rect.x = geometryInfo->GetLabelOffset();
+ rect.SetRight(geometryInfo->GetAccelOffset());
+ }
+
+ DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
+
+ // draw the accel string
+ if ( !accel.empty() )
+ {
+ // menubar items shouldn't have them
+ wxCHECK_RET( geometryInfo, _T("accel strings only valid for menus") );
+
+ rect.x = geometryInfo->GetAccelOffset();
+ rect.SetRight(geometryInfo->GetSize().x);
+
+ // NB: no accel index here
+ DrawLabel(dc, accel, rect, flags, wxALIGN_CENTRE_VERTICAL);
+ }
+
+ // draw the submenu indicator
+ if ( flags & wxCONTROL_ISSUBMENU )
+ {
+ wxCHECK_RET( geometryInfo, _T("wxCONTROL_ISSUBMENU only valid for menus") );
+
+ rect.x = geometryInfo->GetSize().x - MENU_RIGHT_MARGIN;
+ rect.width = MENU_RIGHT_MARGIN;
+
+ DrawArrow(dc, wxRIGHT, rect, flags);
+ }
}
void wxGTKRenderer::DrawMenuSeparator(wxDC& dc,
wxCoord y,
const wxMenuGeometryInfo& geomInfo)
{
- wxFAIL_MSG(_T("TODO"));
+ DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
}
wxSize wxGTKRenderer::GetMenuBarItemSize(const wxSize& sizeText) const
{
- return sizeText;
+ wxSize size = sizeText;
+
+ // TODO: make this configurable
+ size.x += 2*MENU_HORZ_MARGIN;
+ size.y += 2*MENU_VERT_MARGIN;
+
+ return size;
}
wxMenuGeometryInfo *wxGTKRenderer::GetMenuGeometry(wxWindow *win,
const wxMenu& menu) const
{
- wxFAIL_MSG(_T("TODO"));
+ // prepare the dc: for now we draw all the items with the system font
+ wxClientDC dc(win);
+ dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
+
+ // the height of a normal item
+ wxCoord heightText = dc.GetCharHeight();
+
+ // the total height
+ wxCoord height = 0;
+
+ // the max length of label and accel strings: the menu width is the sum of
+ // them, even if they're for different items (as the accels should be
+ // aligned)
+ //
+ // the max length of the bitmap is never 0 as Windows always leaves enough
+ // space for a check mark indicator
+ wxCoord widthLabelMax = 0,
+ widthAccelMax = 0,
+ widthBmpMax = MENU_LEFT_MARGIN;
+
+ for ( wxMenuItemList::Node *node = menu.GetMenuItems().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ // height of this item
+ wxCoord h;
+
+ wxMenuItem *item = node->GetData();
+ if ( item->IsSeparator() )
+ {
+ h = MENU_SEPARATOR_HEIGHT;
+ }
+ else // not separator
+ {
+ h = heightText;
- return NULL;
+ wxCoord widthLabel;
+ dc.GetTextExtent(item->GetLabel(), &widthLabel, NULL);
+ if ( widthLabel > widthLabelMax )
+ {
+ widthLabelMax = widthLabel;
+ }
+
+ wxCoord widthAccel;
+ dc.GetTextExtent(item->GetAccelString(), &widthAccel, NULL);
+ if ( widthAccel > widthAccelMax )
+ {
+ widthAccelMax = widthAccel;
+ }
+
+ const wxBitmap& bmp = item->GetBitmap();
+ if ( bmp.Ok() )
+ {
+ wxCoord widthBmp = bmp.GetWidth();
+ if ( widthBmp > widthBmpMax )
+ widthBmpMax = widthBmp;
+ }
+ //else if ( item->IsCheckable() ): no need to check for this as
+ // MENU_LEFT_MARGIN is big enough to show the check mark
+ }
+
+ h += 2*MENU_VERT_MARGIN;
+
+ // remember the item position and height
+ item->SetGeometry(height, h);
+
+ height += h;
+ }
+
+ // bundle the metrics into a struct and return it
+ wxGTKMenuGeometryInfo *gi = new wxGTKMenuGeometryInfo;
+
+ gi->m_ofsLabel = widthBmpMax + 2*MENU_BMP_MARGIN;
+ gi->m_ofsAccel = gi->m_ofsLabel + widthLabelMax;
+ if ( widthAccelMax > 0 )
+ {
+ // if we actually have any accesl, add a margin
+ gi->m_ofsAccel += MENU_ACCEL_MARGIN;
+ }
+
+ gi->m_heightItem = heightText + 2*MENU_VERT_MARGIN;
+
+ gi->m_size.x = gi->m_ofsAccel + widthAccelMax + MENU_RIGHT_MARGIN;
+ gi->m_size.y = height;
+
+ return gi;
}
// ----------------------------------------------------------------------------
void wxGTKRenderer::DoDrawBackground(wxDC& dc,
const wxColour& col,
- const wxRect& rect)
+ const wxRect& rect,
+ wxWindow *window )
{
wxBrush brush(col, wxSOLID);
dc.SetBrush(brush);
void wxGTKRenderer::DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect,
- int flags)
+ int flags,
+ wxWindow *window )
{
wxColour colBg = col.Ok() ? col : GetBackgroundColour(flags);
- DoDrawBackground(dc, colBg, rect);
+ DoDrawBackground(dc, colBg, rect, window );
}
// ----------------------------------------------------------------------------
"$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$.$."
};
-
-wxIcon wxGTKRenderer::GetStdIcon(int which) const
+wxBitmap wxGTKArtProvider::CreateBitmap(const wxArtID& id,
+ const wxArtClient& WXUNUSED(client),
+ const wxSize& WXUNUSED(size))
{
- switch(which)
- {
- case wxICON_INFORMATION:
- return wxIcon(info_xpm);
-
- case wxICON_QUESTION:
- return wxIcon(question_xpm);
-
- case wxICON_EXCLAMATION:
- return wxIcon(warning_xpm);
-
- default:
- wxFAIL_MSG(wxT("requested non existent standard icon"));
- // still fall through
-
- case wxICON_HAND:
- return wxIcon(error_xpm);
- }
+ if ( id == wxART_INFORMATION )
+ return wxBitmap(info_xpm);
+ if ( id == wxART_ERROR )
+ return wxBitmap(error_xpm);
+ if ( id == wxART_WARNING )
+ return wxBitmap(warning_xpm);
+ if ( id == wxART_QUESTION )
+ return wxBitmap(question_xpm);
+ return wxNullBitmap;
}