-
-// ----------------------------------------------------------------------------
-// label
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::DrawFocusRect(wxDC& dc, const wxRect& rect)
-{
- // VZ: this doesn't work under Windows, the dotted pen has dots of 3
- // pixels each while we really need dots here... PS_ALTERNATE might
- // work, but it is for NT 5 only
-#if 0
- DrawRect(dc, &rect, wxPen(*wxBLACK, 0, wxDOT));
-#else
- // draw the pixels manually: note that to behave in the same manner as
- // DrawRect(), we must exclude the bottom and right borders from the
- // rectangle
- wxCoord x1 = rect.GetLeft(),
- y1 = rect.GetTop(),
- x2 = rect.GetRight(),
- y2 = rect.GetBottom();
-
- dc.SetPen(wxPen(*wxBLACK, 0, wxSOLID));
-
- // this seems to be closer than what Windows does than wxINVERT although
- // I'm still not sure if it's correct
- dc.SetLogicalFunction(wxAND_REVERSE);
-
- wxCoord z;
- for ( z = x1 + 1; z < x2; z += 2 )
- dc.DrawPoint(z, rect.GetTop());
-
- wxCoord shift = z == x2 ? 0 : 1;
- for ( z = y1 + shift; z < y2; z += 2 )
- dc.DrawPoint(x2, z);
-
- shift = z == y2 ? 0 : 1;
- for ( z = x2 - shift; z > x1; z -= 2 )
- dc.DrawPoint(z, y2);
-
- shift = z == x1 ? 0 : 1;
- for ( z = y2 - shift; z > y1; z -= 2 )
- dc.DrawPoint(x1, z);
-
- dc.SetLogicalFunction(wxCOPY);
-#endif // 0/1
-}
-
-void wxMetalRenderer::DrawLabelShadow(wxDC& dc,
- const wxString& label,
- const wxRect& rect,
- int alignment,
- int indexAccel)
-{
- // draw shadow of the text
- dc.SetTextForeground(m_colHighlight);
- wxRect rectShadow = rect;
- rectShadow.x++;
- rectShadow.y++;
- dc.DrawLabel(label, rectShadow, alignment, indexAccel);
-
- // make the text grey
- dc.SetTextForeground(m_colDarkGrey);
-}
-
-void wxMetalRenderer::DrawLabel(wxDC& dc,
- const wxString& label,
- const wxRect& rect,
- int flags,
- int alignment,
- int indexAccel,
- wxRect *rectBounds)
-{
- DoDrawLabel(dc, label, rect, flags, alignment, indexAccel, rectBounds);
-}
-
-void wxMetalRenderer::DoDrawLabel(wxDC& dc,
- const wxString& label,
- const wxRect& rect,
- int flags,
- int alignment,
- int indexAccel,
- wxRect *rectBounds,
- const wxPoint& focusOffset)
-{
- // the underscores are not drawn for focused controls in wxMSW
- if ( flags & wxCONTROL_FOCUSED )
- {
- indexAccel = -1;
- }
-
- if ( flags & wxCONTROL_DISABLED )
- {
- // the combination of wxCONTROL_SELECTED and wxCONTROL_DISABLED
- // currently only can happen for a menu item and it seems that Windows
- // doesn't draw the shadow in this case, so we don't do it neither
- if ( flags & wxCONTROL_SELECTED )
- {
- // just make the label text greyed out
- dc.SetTextForeground(m_colDarkGrey);
- }
- else // draw normal disabled label
- {
- DrawLabelShadow(dc, label, rect, alignment, indexAccel);
- }
- }
-
- wxRect rectLabel;
- dc.DrawLabel(label, wxNullBitmap, rect, alignment, indexAccel, &rectLabel);
-
- if ( flags & wxCONTROL_DISABLED )
- {
- // restore the fg colour
- dc.SetTextForeground(*wxBLACK);
- }
-
- if ( flags & wxCONTROL_FOCUSED )
- {
- if ( focusOffset.x || focusOffset.y )
- {
- rectLabel.Inflate(focusOffset.x, focusOffset.y);
- }
-
- DrawFocusRect(dc, rectLabel);
- }
-
- if ( rectBounds )
- *rectBounds = rectLabel;
-}
-
-void wxMetalRenderer::DrawButtonLabel(wxDC& dc,
- const wxString& label,
- const wxBitmap& image,
- const wxRect& rect,
- int flags,
- int alignment,
- int indexAccel,
- wxRect *rectBounds)
-{
- // the underscores are not drawn for focused controls in wxMSW
- if ( flags & wxCONTROL_PRESSED )
- {
- indexAccel = -1;
- }
-
- wxRect rectLabel = rect;
- if ( !label.empty() )
- {
- // shift the label if a button is pressed
- if ( flags & wxCONTROL_PRESSED )
- {
- rectLabel.x++;
- rectLabel.y++;
- }
-
- if ( flags & wxCONTROL_DISABLED )
- {
- DrawLabelShadow(dc, label, rectLabel, alignment, indexAccel);
- }
-
- // leave enough space for the focus rectangle
- if ( flags & wxCONTROL_FOCUSED )
- {
- rectLabel.Inflate(-2);
- }
- }
-
- dc.DrawLabel(label, image, rectLabel, alignment, indexAccel, rectBounds);
-
- if ( !label.empty() && (flags & wxCONTROL_FOCUSED) )
- {
- if ( flags & wxCONTROL_PRESSED )
- {
- // the focus rectangle is never pressed, so undo the shift done
- // above
- rectLabel.x--;
- rectLabel.y--;
- rectLabel.width--;
- rectLabel.height--;
- }
-
- DrawFocusRect(dc, rectLabel);
- }
-}
-
-// ----------------------------------------------------------------------------
-// (check)listbox items
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::DrawItem(wxDC& dc,
- const wxString& label,
- const wxRect& rect,
- int flags)
-{
- wxDCTextColourChanger colChanger(dc);
-
- if ( flags & wxCONTROL_SELECTED )
- {
- colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
-
- wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
- dc.SetBrush(wxBrush(colBg, wxSOLID));
- dc.SetPen(wxPen(colBg, 0, wxSOLID));
- dc.DrawRectangle(rect);
- }
-
- wxRect rectText = rect;
- rectText.x += 2;
- rectText.width -= 2;
- dc.DrawLabel(label, wxNullBitmap, rectText);
-
- if ( flags & wxCONTROL_FOCUSED )
- {
- DrawFocusRect(dc, rect);
- }
-}
-
-void wxMetalRenderer::DrawCheckItem(wxDC& dc,
- const wxString& label,
- const wxBitmap& bitmap,
- const wxRect& rect,
- int flags)
-{
- wxBitmap bmp;
- if ( bitmap.Ok() )
- {
- bmp = bitmap;
- }
- else // use default bitmap
- {
- IndicatorStatus i = flags & wxCONTROL_CHECKED
- ? IndicatorStatus_Checked
- : IndicatorStatus_Unchecked;
-
- if ( !m_bmpCheckBitmaps[i].Ok() )
- {
- m_bmpCheckBitmaps[i] = wxBitmap(xpmChecked[i]);
- }
-
- bmp = m_bmpCheckBitmaps[i];
- }
-
- dc.DrawBitmap(bmp, rect.x, rect.y + (rect.height - bmp.GetHeight()) / 2 - 1,
- TRUE /* use mask */);
-
- wxRect rectLabel = rect;
- int bmpWidth = bmp.GetWidth();
- rectLabel.x += bmpWidth;
- rectLabel.width -= bmpWidth;
-
- DrawItem(dc, label, rectLabel, flags);
-}
-
-// ----------------------------------------------------------------------------
-// check/radio buttons
-// ----------------------------------------------------------------------------
-
-wxBitmap wxMetalRenderer::GetIndicator(IndicatorType indType, int flags)
-{
- IndicatorState indState;
- if ( flags & wxCONTROL_SELECTED )
- indState = flags & wxCONTROL_DISABLED ? IndicatorState_SelectedDisabled
- : IndicatorState_Selected;
- else if ( flags & wxCONTROL_DISABLED )
- indState = IndicatorState_Disabled;
- else if ( flags & wxCONTROL_PRESSED )
- indState = IndicatorState_Pressed;
- else
- indState = IndicatorState_Normal;
-
- IndicatorStatus indStatus = flags & wxCONTROL_CHECKED
- ? IndicatorStatus_Checked
- : IndicatorStatus_Unchecked;
-
- wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus];
- if ( !bmp.Ok() )
- {
- const char **xpm = xpmIndicators[indType][indState][indStatus];
- if ( xpm )
- {
- // create and cache it
- bmp = wxBitmap(xpm);
- m_bmpIndicators[indType][indState][indStatus] = bmp;
- }
- }
-
- return bmp;
-}
-
-void wxMetalRenderer::DrawCheckOrRadioButton(wxDC& dc,
- const wxString& label,
- const wxBitmap& bitmap,
- const wxRect& rect,
- int flags,
- wxAlignment align,
- int indexAccel,
- wxCoord focusOffsetY)
-{
- // calculate the position of the bitmap and of the label
- wxCoord heightBmp = bitmap.GetHeight();
- wxCoord xBmp,
- yBmp = rect.y + (rect.height - heightBmp) / 2;
-
- wxRect rectLabel;
- dc.GetMultiLineTextExtent(label, NULL, &rectLabel.height);
- rectLabel.y = rect.y + (rect.height - rectLabel.height) / 2;
-
- // align label vertically with the bitmap - looks nicer like this
- rectLabel.y -= (rectLabel.height - heightBmp) % 2;
-
- // calc horz position
- if ( align == wxALIGN_RIGHT )
- {
- xBmp = rect.GetRight() - bitmap.GetWidth();
- rectLabel.x = rect.x + 3;
- rectLabel.SetRight(xBmp);
- }
- else // normal (checkbox to the left of the text) case
- {
- xBmp = rect.x;
- rectLabel.x = xBmp + bitmap.GetWidth() + 5;
- rectLabel.SetRight(rect.GetRight());
- }
-
- dc.DrawBitmap(bitmap, xBmp, yBmp, TRUE /* use mask */);
-
- DoDrawLabel(
- dc, label, rectLabel,
- flags,
- wxALIGN_LEFT | wxALIGN_TOP,
- indexAccel,
- NULL, // we don't need bounding rect
- // use custom vert focus rect offset
- wxPoint(FOCUS_RECT_OFFSET_X, focusOffsetY)
- );
-}
-
-void wxMetalRenderer::DrawRadioButton(wxDC& dc,
- const wxString& label,
- const wxBitmap& bitmap,
- const wxRect& rect,
- int flags,
- wxAlignment align,
- int indexAccel)
-{
- wxBitmap bmp;
- if ( bitmap.Ok() )
- bmp = bitmap;
- else
- bmp = GetRadioBitmap(flags);
-
- DrawCheckOrRadioButton(dc, label,
- bmp,
- rect, flags, align, indexAccel,
- FOCUS_RECT_OFFSET_Y); // default focus rect offset
-}
-
-void wxMetalRenderer::DrawCheckButton(wxDC& dc,
- const wxString& label,
- const wxBitmap& bitmap,
- const wxRect& rect,
- int flags,
- wxAlignment align,
- int indexAccel)
-{
- wxBitmap bmp;
- if ( bitmap.Ok() )
- bmp = bitmap;
- else
- bmp = GetCheckBitmap(flags);
-
- DrawCheckOrRadioButton(dc, label,
- bmp,
- rect, flags, align, indexAccel,
- 0); // no focus rect offset for checkboxes
-}
-
-void wxMetalRenderer::DrawToolBarButton(wxDC& dc,
- const wxString& label,
- const wxBitmap& bitmap,
- const wxRect& rectOrig,
- int flags)
-{
- if ( !label.empty() || bitmap.Ok() )
- {
- wxRect rect = rectOrig;
- rect.Deflate(BORDER_THICKNESS);
-
- if ( flags & wxCONTROL_PRESSED )
- {
- DrawBorder(dc, wxBORDER_SUNKEN, rect, flags);
- }
- else if ( flags & wxCONTROL_CURRENT )
- {
- DrawBorder(dc, wxBORDER_RAISED, rect, flags);
- }
-
- dc.DrawLabel(label, bitmap, rect, wxALIGN_CENTRE);
- }
- else // a separator
- {
- // leave a small gap aroudn the line, also account for the toolbar
- // border itself
- DrawVerticalLine(dc, rectOrig.x + rectOrig.width/2,
- rectOrig.y + 2*BORDER_THICKNESS,
- rectOrig.GetBottom() - BORDER_THICKNESS);
- }
-}
-
-// ----------------------------------------------------------------------------
-// text control
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::DrawTextLine(wxDC& dc,
- const wxString& text,
- const wxRect& rect,
- int selStart,
- int selEnd,
- int flags)
-{
- // nothing special to do here
- StandardDrawTextLine(dc, text, rect, selStart, selEnd, flags);
-}
-
-void wxMetalRenderer::DrawLineWrapMark(wxDC& dc, const wxRect& rect)
-{
- // we don't draw them
-}
-
-// ----------------------------------------------------------------------------
-// notebook
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::DrawTab(wxDC& dc,
- const wxRect& rectOrig,
- wxDirection dir,
- const wxString& label,
- const wxBitmap& bitmap,
- int flags,
- int indexAccel)
-{
- wxRect rect = rectOrig;
-
- // the current tab is drawn indented (to the top for default case) and
- // bigger than the other ones
- const wxSize indent = GetTabIndent();
- if ( flags & wxCONTROL_SELECTED )
- {
- switch ( dir )
- {
- default:
- wxFAIL_MSG(_T("invaild notebook tab orientation"));
- // fall through
-
- case wxTOP:
- rect.Inflate(indent.x, 0);
- rect.y -= indent.y;
- rect.height += indent.y;
- break;
-
- case wxBOTTOM:
- rect.Inflate(indent.x, 0);
- rect.height += indent.y;
- break;
-
- case wxLEFT:
- case wxRIGHT:
- wxFAIL_MSG(_T("TODO"));
- break;
- }
- }
-
- // draw the text, image and the focus around them (if necessary)
- wxRect rectLabel = rect;
- rectLabel.Deflate(1, 1);
- DrawButtonLabel(dc, label, bitmap, rectLabel,
- flags, wxALIGN_CENTRE, indexAccel);
-
- // now draw the tab border itself (maybe use DrawRoundedRectangle()?)
- static const wxCoord CUTOFF = 2; // radius of the rounded corner
- wxCoord x = rect.x,
- y = rect.y,
- x2 = rect.GetRight(),
- y2 = rect.GetBottom();
-
- // FIXME: all this code will break if the tab indent or the border width,
- // it is tied to the fact that both of them are equal to 2
- switch ( dir )
- {
- default:
- case wxTOP:
- dc.SetPen(m_penHighlight);
- dc.DrawLine(x, y2, x, y + CUTOFF);
- dc.DrawLine(x, y + CUTOFF, x + CUTOFF, y);
- dc.DrawLine(x + CUTOFF, y, x2 - CUTOFF + 1, y);
-
- dc.SetPen(m_penBlack);
- dc.DrawLine(x2, y2, x2, y + CUTOFF);
- dc.DrawLine(x2, y + CUTOFF, x2 - CUTOFF, y);
-
- dc.SetPen(m_penDarkGrey);
- dc.DrawLine(x2 - 1, y2, x2 - 1, y + CUTOFF - 1);
-
- if ( flags & wxCONTROL_SELECTED )
- {
- dc.SetPen(m_penLightGrey);
-
- // overwrite the part of the border below this tab
- dc.DrawLine(x + 1, y2 + 1, x2 - 1, y2 + 1);
-
- // and the shadow of the tab to the left of us
- dc.DrawLine(x + 1, y + CUTOFF + 1, x + 1, y2 + 1);
- }
- break;
-
- case wxBOTTOM:
- dc.SetPen(m_penHighlight);
- // we need to continue one pixel further to overwrite the corner of
- // the border for the selected tab
- dc.DrawLine(x, y - (flags & wxCONTROL_SELECTED ? 1 : 0),
- x, y2 - CUTOFF);
- dc.DrawLine(x, y2 - CUTOFF, x + CUTOFF, y2);
-
- dc.SetPen(m_penBlack);
- dc.DrawLine(x + CUTOFF, y2, x2 - CUTOFF + 1, y2);
- dc.DrawLine(x2, y, x2, y2 - CUTOFF);
- dc.DrawLine(x2, y2 - CUTOFF, x2 - CUTOFF, y2);
-
- dc.SetPen(m_penDarkGrey);
- dc.DrawLine(x + CUTOFF, y2 - 1, x2 - CUTOFF + 1, y2 - 1);
- dc.DrawLine(x2 - 1, y, x2 - 1, y2 - CUTOFF + 1);
-
- if ( flags & wxCONTROL_SELECTED )
- {
- dc.SetPen(m_penLightGrey);
-
- // overwrite the part of the (double!) border above this tab
- dc.DrawLine(x + 1, y - 1, x2 - 1, y - 1);
- dc.DrawLine(x + 1, y - 2, x2 - 1, y - 2);
-
- // and the shadow of the tab to the left of us
- dc.DrawLine(x + 1, y2 - CUTOFF, x + 1, y - 1);
- }
- break;
-
- case wxLEFT:
- case wxRIGHT:
- wxFAIL_MSG(_T("TODO"));
- }
-}
-
-// ----------------------------------------------------------------------------
-// slider
-// ----------------------------------------------------------------------------
-
-wxSize wxMetalRenderer::GetSliderThumbSize(const wxRect& rect,
- wxOrientation orient) const
-{
- wxSize size;
-
- wxRect rectShaft = GetSliderShaftRect(rect, orient);
- if ( orient == wxHORIZONTAL )
- {
- size.y = rect.height - 6;
- size.x = wxMin(size.y / 2, rectShaft.width);
- }
- else // vertical
- {
- size.x = rect.width - 6;
- size.y = wxMin(size.x / 2, rectShaft.height);
- }
-
- return size;
-}
-
-wxRect wxMetalRenderer::GetSliderShaftRect(const wxRect& rectOrig,
- wxOrientation orient) const
-{
- static const wxCoord SLIDER_MARGIN = 6;
-
- wxRect rect = rectOrig;
-
- if ( orient == wxHORIZONTAL )
- {
- // make the rect of minimal width and centre it
- rect.height = 2*BORDER_THICKNESS;
- rect.y = rectOrig.y + (rectOrig.height - rect.height) / 2;
- if ( rect.y < 0 )
- rect.y = 0;
-
- // leave margins on the sides
- rect.Deflate(SLIDER_MARGIN, 0);
- }
- else // vertical
- {
- // same as above but in other direction
- rect.width = 2*BORDER_THICKNESS;
- rect.x = rectOrig.x + (rectOrig.width - rect.width) / 2;
- if ( rect.x < 0 )
- rect.x = 0;
-
- rect.Deflate(0, SLIDER_MARGIN);
- }
-
- return rect;
-}
-
-void wxMetalRenderer::DrawSliderShaft(wxDC& dc,
- const wxRect& rectOrig,
- wxOrientation orient,
- int flags,
- wxRect *rectShaft)
-{
- if ( flags & wxCONTROL_FOCUSED )
- {
- DrawFocusRect(dc, rectOrig);
- }
-
- wxRect rect = GetSliderShaftRect(rectOrig, orient);
-
- if ( rectShaft )
- *rectShaft = rect;
-
- DrawSunkenBorder(dc, &rect);
-}
-
-void wxMetalRenderer::DrawSliderThumb(wxDC& dc,
- const wxRect& rect,
- wxOrientation orient,
- int flags)
-{
- /*
- we are drawing a shape of this form
-
- HHHHHHB <--- y
- H DB
- H DB
- H DB where H is hightlight colour
- H DB D dark grey
- H DB B black
- H DB
- H DB <--- y3
- H DB
- HDB
- B <--- y2
-
- ^ ^ ^
- | | |
- x x3 x2
-
- The interior of this shape is filled with the hatched brush if the thumb
- is pressed.
- */
-
- DrawBackground(dc, wxNullColour, rect, flags);
-
- bool transpose = orient == wxVERTICAL;
-
- wxCoord x, y, x2, y2;
- if ( transpose )
- {
- x = rect.y;
- y = rect.x;
- x2 = rect.GetBottom();
- y2 = rect.GetRight();
- }
- else
- {
- x = rect.x;
- y = rect.y;
- x2 = rect.GetRight();
- y2 = rect.GetBottom();
- }
-
- // the size of the pointed part of the thumb
- wxCoord sizeArrow = (transpose ? rect.height : rect.width) / 2;
-
- wxCoord x3 = x + sizeArrow,
- y3 = y2 - sizeArrow;
-
- dc.SetPen(m_penHighlight);
- DrawLine(dc, x, y, x2, y, transpose);
- DrawLine(dc, x, y + 1, x, y2 - sizeArrow, transpose);
- DrawLine(dc, x, y3, x3, y2, transpose);
-
- dc.SetPen(m_penBlack);
- DrawLine(dc, x3, y2, x2, y3, transpose);
- DrawLine(dc, x2, y3, x2, y - 1, transpose);
-
- dc.SetPen(m_penDarkGrey);
- DrawLine(dc, x3, y2 - 1, x2 - 1, y3, transpose);
- DrawLine(dc, x2 - 1, y3, x2 - 1, y, transpose);
-
- if ( flags & wxCONTROL_PRESSED )
- {
- // TODO: MSW fills the entire area inside, not just the rect
- wxRect rectInt = rect;
- if ( transpose )
- rectInt.SetRight(y3);
- else
- rectInt.SetBottom(y3);
- rectInt.Deflate(2);
-
-#if !defined(__WXMGL__)
- static const char *stipple_xpm[] = {
- /* columns rows colors chars-per-pixel */
- "2 2 2 1",
- " c None",
- "w c white",
- /* pixels */
- "w ",
- " w",
- };
-#else
- // VS: MGL can only do 8x8 stipple brushes
- static const char *stipple_xpm[] = {
- /* columns rows colors chars-per-pixel */
- "8 8 2 1",
- " c None",
- "w c white",
- /* pixels */
- "w w w w ",
- " w w w w",
- "w w w w ",
- " w w w w",
- "w w w w ",
- " w w w w",
- "w w w w ",
- " w w w w",
- };
-#endif
- dc.SetBrush(wxBrush(stipple_xpm));
-
- dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, SHADOW_HIGHLIGHT));
- dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, CONTROL));
- dc.SetPen(*wxTRANSPARENT_PEN);
- dc.DrawRectangle(rectInt);
- }
-}
-
-void wxMetalRenderer::DrawSliderTicks(wxDC& dc,
- const wxRect& rect,
- const wxSize& sizeThumb,
- wxOrientation orient,
- int start,
- int end,
- int step,
- int flags)
-{
- if ( end == start )
- {
- // empty slider?
- return;
- }
-
- // the variable names correspond to horizontal case, but they can be used
- // for both orientations
- wxCoord x1, x2, y1, y2, len, widthThumb;
- if ( orient == wxHORIZONTAL )
- {
- x1 = rect.GetLeft();
- x2 = rect.GetRight();
-
- // draw from bottom to top to leave one pixel space between the ticks
- // and the slider as Windows do
- y1 = rect.GetBottom();
- y2 = rect.GetTop();
-
- len = rect.width;
-
- widthThumb = sizeThumb.x;
- }
- else // vertical
- {
- x1 = rect.GetTop();
- x2 = rect.GetBottom();
-
- y1 = rect.GetRight();
- y2 = rect.GetLeft();
-
- len = rect.height;
-
- widthThumb = sizeThumb.y;
- }
-
- // the first tick should be positioned in such way that a thumb drawn in
- // the first position points down directly to it
- x1 += widthThumb / 2;
- x2 -= widthThumb / 2;
-
- // this also means that we have slightly less space for the ticks in
- // between the first and the last
- len -= widthThumb;
-
- dc.SetPen(m_penBlack);
-
- int range = end - start;
- for ( int n = 0; n < range; n += step )
- {
- wxCoord x = x1 + (len*n) / range;
-
- DrawLine(dc, x, y1, x, y2, orient == wxVERTICAL);
- }
-
- // always draw the line at the end position
- DrawLine(dc, x2, y1, x2, y2, orient == wxVERTICAL);
-}
-
-// ----------------------------------------------------------------------------
-// menu and menubar
-// ----------------------------------------------------------------------------
-
-// wxMetalMenuGeometryInfo: the wxMenuGeometryInfo used by wxMetalRenderer
-class WXDLLEXPORT wxMetalMenuGeometryInfo : 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 *
- wxMetalRenderer::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 = 18;
-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 wxMetalRenderer::DrawMenuBarItem(wxDC& dc,
- const wxRect& rectOrig,
- const wxString& label,
- int flags,
- int indexAccel)
-{
- wxRect rect = rectOrig;
- rect.height--;
-
- wxDCTextColourChanger colChanger(dc);
-
- if ( flags & wxCONTROL_SELECTED )
- {
- colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
-
- wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
- dc.SetBrush(wxBrush(colBg, wxSOLID));
- dc.SetPen(wxPen(colBg, 0, wxSOLID));
- dc.DrawRectangle(rect);
- }
-
- // don't draw the focus rect around menu bar items
- DrawLabel(dc, label, rect, flags & ~wxCONTROL_FOCUSED,
- wxALIGN_CENTRE, indexAccel);
-}
-
-void wxMetalRenderer::DrawMenuItem(wxDC& dc,
- wxCoord y,
- const wxMenuGeometryInfo& gi,
- const wxString& label,
- const wxString& accel,
- const wxBitmap& bitmap,
- int flags,
- int indexAccel)
-{
- const wxMetalMenuGeometryInfo& geometryInfo =
- (const wxMetalMenuGeometryInfo&)gi;
-
- wxRect rect;
- rect.x = 0;
- rect.y = y;
- rect.width = geometryInfo.GetSize().x;
- rect.height = geometryInfo.GetItemHeight();
-
- // draw the selected item specially
- wxDCTextColourChanger colChanger(dc);
- if ( flags & wxCONTROL_SELECTED )
- {
- colChanger.Set(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
-
- wxColour colBg = wxSCHEME_COLOUR(m_scheme, HIGHLIGHT);
- dc.SetBrush(wxBrush(colBg, wxSOLID));
- dc.SetPen(wxPen(colBg, 0, wxSOLID));
- dc.DrawRectangle(rect);
- }
-
- // draw the bitmap: use the bitmap provided or the standard checkmark for
- // the checkable items
- wxBitmap bmp = bitmap;
- if ( !bmp.Ok() && (flags & wxCONTROL_CHECKED) )
- {
- bmp = GetIndicator(IndicatorType_Menu, flags);
- }
-
- if ( bmp.Ok() )
- {
- rect.SetRight(geometryInfo.GetLabelOffset());
- wxControlRenderer::DrawBitmap(dc, bmp, rect);
- }
-
- // draw the label
- rect.x = geometryInfo.GetLabelOffset();
- rect.SetRight(geometryInfo.GetAccelOffset());
-
- DrawLabel(dc, label, rect, flags, wxALIGN_CENTRE_VERTICAL, indexAccel);
-
- // draw the accel string
- 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 )
- {
- rect.x = geometryInfo.GetSize().x - MENU_RIGHT_MARGIN;
- rect.width = MENU_RIGHT_MARGIN;
-
- wxArrowStyle arrowStyle;
- if ( flags & wxCONTROL_DISABLED )
- arrowStyle = flags & wxCONTROL_SELECTED ? Arrow_InversedDisabled
- : Arrow_Disabled;
- else if ( flags & wxCONTROL_SELECTED )
- arrowStyle = Arrow_Inversed;
- else
- arrowStyle = Arrow_Normal;
-
- DrawArrow(dc, rect, Arrow_Right, arrowStyle);
- }
-}
-
-void wxMetalRenderer::DrawMenuSeparator(wxDC& dc,
- wxCoord y,
- const wxMenuGeometryInfo& geomInfo)
-{
- DrawHorizontalLine(dc, y + MENU_VERT_MARGIN, 0, geomInfo.GetSize().x);
-}
-
-wxSize wxMetalRenderer::GetMenuBarItemSize(const wxSize& sizeText) const
-{
- wxSize size = sizeText;
-
- // FIXME: menubar height is configurable under Windows
- size.x += 12;
- size.y += 6;
-
- return size;
-}
-
-wxMenuGeometryInfo *wxMetalRenderer::GetMenuGeometry(wxWindow *win,
- const wxMenu& menu) const
-{
- // 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;
-
- 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
- wxMetalMenuGeometryInfo *gi = new wxMetalMenuGeometryInfo;
-
- 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;
-}
-
-// ----------------------------------------------------------------------------
-// status bar
-// ----------------------------------------------------------------------------
-
-static const wxCoord STATBAR_BORDER_X = 2;
-static const wxCoord STATBAR_BORDER_Y = 2;
-
-wxSize wxMetalRenderer::GetStatusBarBorders(wxCoord *borderBetweenFields) const
-{
- if ( borderBetweenFields )
- *borderBetweenFields = 2;
-
- return wxSize(STATBAR_BORDER_X, STATBAR_BORDER_Y);
-}
-
-void wxMetalRenderer::DrawStatusField(wxDC& dc,
- const wxRect& rect,
- const wxString& label,
- int flags)
-{
- wxRect rectIn;
-
- if ( flags & wxCONTROL_ISDEFAULT )
- {
- // draw the size grip: it is a normal rect except that in the lower
- // right corner we have several bands which may be used for dragging
- // the status bar corner
- //
- // each band consists of 4 stripes: m_penHighlight, double
- // m_penDarkGrey and transparent one
- wxCoord x2 = rect.GetRight(),
- y2 = rect.GetBottom();
-
- // draw the upper left part of the rect normally
- dc.SetPen(m_penDarkGrey);
- dc.DrawLine(rect.GetLeft(), rect.GetTop(), rect.GetLeft(), y2);
- dc.DrawLine(rect.GetLeft() + 1, rect.GetTop(), x2, rect.GetTop());
-
- // draw the grey stripes of the grip
- size_t n;
- wxCoord ofs = WIDTH_STATUSBAR_GRIP_BAND - 1;
- for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
- {
- dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
- dc.DrawLine(x2 - ofs, y2 - 1, x2, y2 - ofs - 1);
- }
-
- // draw the white stripes
- dc.SetPen(m_penHighlight);
- ofs = WIDTH_STATUSBAR_GRIP_BAND + 1;
- for ( n = 0; n < NUM_STATUSBAR_GRIP_BANDS; n++, ofs += WIDTH_STATUSBAR_GRIP_BAND )
- {
- dc.DrawLine(x2 - ofs + 1, y2 - 1, x2, y2 - ofs);
- }
-
- // draw the remaining rect boundaries
- ofs -= WIDTH_STATUSBAR_GRIP_BAND;
- dc.DrawLine(x2, rect.GetTop(), x2, y2 - ofs + 1);
- dc.DrawLine(rect.GetLeft(), y2, x2 - ofs + 1, y2);
-
- rectIn = rect;
- rectIn.Deflate(1);
-
- rectIn.width -= STATUSBAR_GRIP_SIZE;
- }
- else // normal pane
- {
- DrawBorder(dc, wxBORDER_STATIC, rect, flags, &rectIn);
- }
-
- rectIn.Deflate(STATBAR_BORDER_X, STATBAR_BORDER_Y);
-
- wxDCClipper clipper(dc, rectIn);
- DrawLabel(dc, label, rectIn, flags, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
-}
-
-// ----------------------------------------------------------------------------
-// combobox
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::GetComboBitmaps(wxBitmap *bmpNormal,
- wxBitmap *bmpFocus,
- wxBitmap *bmpPressed,
- wxBitmap *bmpDisabled)
-{
- static const wxCoord widthCombo = 16;
- static const wxCoord heightCombo = 17;
-
- wxMemoryDC dcMem;
-
- if ( bmpNormal )
- {
- bmpNormal->Create(widthCombo, heightCombo);
- dcMem.SelectObject(*bmpNormal);
- DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
- Arrow_Down, Arrow_Normal);
- }
-
- if ( bmpPressed )
- {
- bmpPressed->Create(widthCombo, heightCombo);
- dcMem.SelectObject(*bmpPressed);
- DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
- Arrow_Down, Arrow_Pressed);
- }
-
- if ( bmpDisabled )
- {
- bmpDisabled->Create(widthCombo, heightCombo);
- dcMem.SelectObject(*bmpDisabled);
- DrawArrowButton(dcMem, wxRect(0, 0, widthCombo, heightCombo),
- Arrow_Down, Arrow_Disabled);
- }
-}
-
-// ----------------------------------------------------------------------------
-// background
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::DoDrawBackground(wxDC& dc,
- const wxColour& col,
- const wxRect& rect)
-{
- if (col == wxTheme::Get()->GetColourScheme()->Get( wxColourScheme::CONTROL ))
- {
- for (int y = rect.y; y < rect.height+rect.y; y++)
- {
- int intens = 230 + 80 * (rect.y-y) / rect.height;
- dc.SetPen( wxPen( wxColour(intens,intens,intens), 1, wxSOLID ) );
- dc.DrawLine( rect.x, y, rect.x+rect.width, y );
- }
- }
- else
- {
- wxBrush brush(col, wxSOLID);
- dc.SetBrush(brush);
- dc.SetPen(*wxTRANSPARENT_PEN);
- dc.DrawRectangle(rect);
- }
-}
-
-void wxMetalRenderer::DrawBackground(wxDC& dc,
- const wxColour& col,
- const wxRect& rect,
- int flags)
-{
- // just fill it with the given or default bg colour
- wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL);
- DoDrawBackground(dc, colBg, rect);
-}
-
-// ----------------------------------------------------------------------------
-// scrollbar
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::DrawArrow(wxDC& dc,
- wxDirection dir,
- const wxRect& rect,
- int flags)
-{
- // get the bitmap for this arrow
- wxArrowDirection arrowDir;
- switch ( dir )
- {
- case wxLEFT: arrowDir = Arrow_Left; break;
- case wxRIGHT: arrowDir = Arrow_Right; break;
- case wxUP: arrowDir = Arrow_Up; break;
- case wxDOWN: arrowDir = Arrow_Down; break;
-
- default:
- wxFAIL_MSG(_T("unknown arrow direction"));
- return;
- }
-
- wxArrowStyle arrowStyle;
- if ( flags & wxCONTROL_PRESSED )
- {
- // can't be pressed and disabled
- arrowStyle = Arrow_Pressed;
- }
- else
- {
- arrowStyle = flags & wxCONTROL_DISABLED ? Arrow_Disabled : Arrow_Normal;
- }
-
- DrawArrowButton(dc, rect, arrowDir, arrowStyle);
-}
-
-void wxMetalRenderer::DrawArrow(wxDC& dc,
- const wxRect& rect,
- wxArrowDirection arrowDir,
- wxArrowStyle arrowStyle)
-{
- const wxBitmap& bmp = m_bmpArrows[arrowStyle][arrowDir];
-
- // under Windows the arrows always have the same size so just centre it in
- // the provided rectangle
- wxCoord x = rect.x + (rect.width - bmp.GetWidth()) / 2,
- y = rect.y + (rect.height - bmp.GetHeight()) / 2;
-
- // Windows does it like this...
- if ( arrowDir == Arrow_Left )
- x--;
-
- // draw it
- dc.DrawBitmap(bmp, x, y, TRUE /* use mask */);
-}
-
-void wxMetalRenderer::DrawArrowButton(wxDC& dc,
- const wxRect& rectAll,
- wxArrowDirection arrowDir,
- wxArrowStyle arrowStyle)
-{
- wxRect rect = rectAll;
- DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
- DrawArrowBorder(dc, &rect, arrowStyle == Arrow_Pressed);
- DrawArrow(dc, rect, arrowDir, arrowStyle);
-}
-
-void wxMetalRenderer::DrawScrollbarThumb(wxDC& dc,
- wxOrientation orient,
- const wxRect& rect,
- int flags)
-{
- // we don't use the flags, the thumb never changes appearance
- wxRect rectThumb = rect;
- DrawArrowBorder(dc, &rectThumb);
- DrawBackground(dc, wxNullColour, rectThumb);
-}
-
-void wxMetalRenderer::DrawScrollbarShaft(wxDC& dc,
- wxOrientation orient,
- const wxRect& rectBar,
- int flags)
-{
- wxColourScheme::StdColour col = flags & wxCONTROL_PRESSED
- ? wxColourScheme::SCROLLBAR_PRESSED
- : wxColourScheme::SCROLLBAR;
- DoDrawBackground(dc, m_scheme->Get(col), rectBar);
-}
-
-void wxMetalRenderer::DrawScrollCorner(wxDC& dc, const wxRect& rect)
-{
- DoDrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), rect);
-}
-
-wxRect wxMetalRenderer::GetScrollbarRect(const wxScrollBar *scrollbar,
- wxScrollBar::Element elem,
- int thumbPos) const
-{
- return StandardGetScrollbarRect(scrollbar, elem,
- thumbPos, m_sizeScrollbarArrow);
-}
-
-wxCoord wxMetalRenderer::GetScrollbarSize(const wxScrollBar *scrollbar)
-{
- return StandardScrollBarSize(scrollbar, m_sizeScrollbarArrow);
-}
-
-wxHitTest wxMetalRenderer::HitTestScrollbar(const wxScrollBar *scrollbar,
- const wxPoint& pt) const
-{
- return StandardHitTestScrollbar(scrollbar, pt, m_sizeScrollbarArrow);
-}
-
-wxCoord wxMetalRenderer::ScrollbarToPixel(const wxScrollBar *scrollbar,
- int thumbPos)
-{
- return StandardScrollbarToPixel(scrollbar, thumbPos, m_sizeScrollbarArrow);
-}
-
-int wxMetalRenderer::PixelToScrollbar(const wxScrollBar *scrollbar,
- wxCoord coord)
-{
- return StandardPixelToScrollbar(scrollbar, coord, m_sizeScrollbarArrow);
-}
-
-// ----------------------------------------------------------------------------
-// top level windows
-// ----------------------------------------------------------------------------
-
-int wxMetalRenderer::HitTestFrame(const wxRect& rect, const wxPoint& pt, int flags) const
-{
- wxRect client = GetFrameClientArea(rect, flags);
-
- if ( client.Inside(pt) )
- return wxHT_TOPLEVEL_CLIENT_AREA;
-
- if ( flags & wxTOPLEVEL_TITLEBAR )
- {
- wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
-
- if ( flags & wxTOPLEVEL_ICON )
- {
- if ( wxRect(client.GetPosition(), GetFrameIconSize()).Inside(pt) )
- return wxHT_TOPLEVEL_ICON;
- }
-
- wxRect btnRect(client.GetRight() - 2 - FRAME_BUTTON_WIDTH,
- client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2,
- FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
-
- if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
- {
- if ( btnRect.Inside(pt) )
- return wxHT_TOPLEVEL_BUTTON_CLOSE;
- btnRect.x -= FRAME_BUTTON_WIDTH + 2;
- }
- if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
- {
- if ( btnRect.Inside(pt) )
- return wxHT_TOPLEVEL_BUTTON_MAXIMIZE;
- btnRect.x -= FRAME_BUTTON_WIDTH;
- }
- if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
- {
- if ( btnRect.Inside(pt) )
- return wxHT_TOPLEVEL_BUTTON_RESTORE;
- btnRect.x -= FRAME_BUTTON_WIDTH;
- }
- if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
- {
- if ( btnRect.Inside(pt) )
- return wxHT_TOPLEVEL_BUTTON_ICONIZE;
- btnRect.x -= FRAME_BUTTON_WIDTH;
- }
- if ( flags & wxTOPLEVEL_BUTTON_HELP )
- {
- if ( btnRect.Inside(pt) )
- return wxHT_TOPLEVEL_BUTTON_HELP;
- btnRect.x -= FRAME_BUTTON_WIDTH;
- }
-
- if ( pt.y >= client.y && pt.y < client.y + FRAME_TITLEBAR_HEIGHT )
- return wxHT_TOPLEVEL_TITLEBAR;
- }
-
- if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
- {
- // we are certainly at one of borders, lets decide which one:
-
- int border = 0;
- // dirty trick, relies on the way wxHT_TOPLEVEL_XXX are defined!
- if ( pt.x < client.x )
- border |= wxHT_TOPLEVEL_BORDER_W;
- else if ( pt.x >= client.width + client.x )
- border |= wxHT_TOPLEVEL_BORDER_E;
- if ( pt.y < client.y )
- border |= wxHT_TOPLEVEL_BORDER_N;
- else if ( pt.y >= client.height + client.y )
- border |= wxHT_TOPLEVEL_BORDER_S;
- return border;
- }
-
- return wxHT_NOWHERE;
-}
-
-void wxMetalRenderer::DrawFrameTitleBar(wxDC& dc,
- const wxRect& rect,
- const wxString& title,
- const wxIcon& icon,
- int flags,
- int specialButton,
- int specialButtonFlags)
-{
- if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
- {
- DrawFrameBorder(dc, rect, flags);
- }
- if ( flags & wxTOPLEVEL_TITLEBAR )
- {
- DrawFrameBackground(dc, rect, flags);
- if ( flags & wxTOPLEVEL_ICON )
- DrawFrameIcon(dc, rect, icon, flags);
- DrawFrameTitle(dc, rect, title, flags);
-
- wxRect client = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
- wxCoord x,y;
- x = client.GetRight() - 2 - FRAME_BUTTON_WIDTH;
- y = client.GetTop() + (FRAME_TITLEBAR_HEIGHT-FRAME_BUTTON_HEIGHT)/2;
-
- if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
- {
- DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_CLOSE,
- (specialButton == wxTOPLEVEL_BUTTON_CLOSE) ?
- specialButtonFlags : 0);
- x -= FRAME_BUTTON_WIDTH + 2;
- }
- if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
- {
- DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_MAXIMIZE,
- (specialButton == wxTOPLEVEL_BUTTON_MAXIMIZE) ?
- specialButtonFlags : 0);
- x -= FRAME_BUTTON_WIDTH;
- }
- if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
- {
- DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_RESTORE,
- (specialButton == wxTOPLEVEL_BUTTON_RESTORE) ?
- specialButtonFlags : 0);
- x -= FRAME_BUTTON_WIDTH;
- }
- if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
- {
- DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_ICONIZE,
- (specialButton == wxTOPLEVEL_BUTTON_ICONIZE) ?
- specialButtonFlags : 0);
- x -= FRAME_BUTTON_WIDTH;
- }
- if ( flags & wxTOPLEVEL_BUTTON_HELP )
- {
- DrawFrameButton(dc, x, y, wxTOPLEVEL_BUTTON_HELP,
- (specialButton == wxTOPLEVEL_BUTTON_HELP) ?
- specialButtonFlags : 0);
- x -= FRAME_BUTTON_WIDTH;
- }
- }
-}
-
-void wxMetalRenderer::DrawFrameBorder(wxDC& dc,
- const wxRect& rect,
- int flags)
-{
- if ( !(flags & wxTOPLEVEL_BORDER) ) return;
-
- wxRect r(rect);
-
- DrawShadedRect(dc, &r, m_penLightGrey, m_penBlack);
- DrawShadedRect(dc, &r, m_penHighlight, m_penDarkGrey);
- DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
- if ( flags & wxTOPLEVEL_RESIZEABLE )
- DrawShadedRect(dc, &r, m_penLightGrey, m_penLightGrey);
-}
-
-void wxMetalRenderer::DrawFrameBackground(wxDC& dc,
- const wxRect& rect,
- int flags)
-{
- if ( !(flags & wxTOPLEVEL_TITLEBAR) ) return;
-
- wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
- wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE) :
- wxSCHEME_COLOUR(m_scheme, TITLEBAR);
-
- wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
- r.height = FRAME_TITLEBAR_HEIGHT;
-
- DrawBackground(dc, col, r);
-}
-
-void wxMetalRenderer::DrawFrameTitle(wxDC& dc,
- const wxRect& rect,
- const wxString& title,
- int flags)
-{
- wxColour col = (flags & wxTOPLEVEL_ACTIVE) ?
- wxSCHEME_COLOUR(m_scheme, TITLEBAR_ACTIVE_TEXT) :
- wxSCHEME_COLOUR(m_scheme, TITLEBAR_TEXT);
-
- wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
- r.height = FRAME_TITLEBAR_HEIGHT;
- if ( flags & wxTOPLEVEL_ICON )
- {
- r.x += FRAME_TITLEBAR_HEIGHT;
- r.width -= FRAME_TITLEBAR_HEIGHT + 2;
- }
- else
- {
- r.x += 1;
- r.width -= 3;
- }
-
- if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
- r.width -= FRAME_BUTTON_WIDTH + 2;
- if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
- r.width -= FRAME_BUTTON_WIDTH;
- if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
- r.width -= FRAME_BUTTON_WIDTH;
- if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
- r.width -= FRAME_BUTTON_WIDTH;
- if ( flags & wxTOPLEVEL_BUTTON_HELP )
- r.width -= FRAME_BUTTON_WIDTH;
-
- dc.SetFont(m_titlebarFont);
- dc.SetTextForeground(col);
-
- wxCoord textW;
- dc.GetTextExtent(title, &textW, NULL);
- if ( textW > r.width )
- {
- // text is too big, let's shorten it and add "..." after it:
- size_t len = title.length();
- wxCoord WSoFar, letterW;
-
- dc.GetTextExtent(wxT("..."), &WSoFar, NULL);
- if ( WSoFar > r.width )
- {
- // not enough space to draw anything
- return;
- }
-
- wxString s;
- s.Alloc(len);
- for (size_t i = 0; i < len; i++)
- {
- dc.GetTextExtent(title[i], &letterW, NULL);
- if ( letterW + WSoFar > r.width )
- break;
- WSoFar += letterW;
- s << title[i];
- }
- s << wxT("...");
- dc.DrawLabel(s, wxNullBitmap, r,
- wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
- }
- else
- dc.DrawLabel(title, wxNullBitmap, r,
- wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
-}
-
-void wxMetalRenderer::DrawFrameIcon(wxDC& dc,
- const wxRect& rect,
- const wxIcon& icon,
- int flags)
-{
- if ( icon.Ok() )
- {
- wxRect r = GetFrameClientArea(rect, flags & ~wxTOPLEVEL_TITLEBAR);
- dc.DrawIcon(icon, r.x, r.y);
- }
-}
-
-void wxMetalRenderer::DrawFrameButton(wxDC& dc,
- wxCoord x, wxCoord y,
- int button,
- int flags)
-{
- wxRect r(x, y, FRAME_BUTTON_WIDTH, FRAME_BUTTON_HEIGHT);
-
- size_t idx = 0;
- switch (button)
- {
- case wxTOPLEVEL_BUTTON_CLOSE: idx = FrameButton_Close; break;
- case wxTOPLEVEL_BUTTON_MAXIMIZE: idx = FrameButton_Maximize; break;
- case wxTOPLEVEL_BUTTON_ICONIZE: idx = FrameButton_Minimize; break;
- case wxTOPLEVEL_BUTTON_RESTORE: idx = FrameButton_Restore; break;
- case wxTOPLEVEL_BUTTON_HELP: idx = FrameButton_Help; break;
- default:
- wxFAIL_MSG(wxT("incorrect button specification"));
- }
-
- if ( flags & wxCONTROL_PRESSED )
- {
- DrawShadedRect(dc, &r, m_penBlack, m_penHighlight);
- DrawShadedRect(dc, &r, m_penDarkGrey, m_penLightGrey);
- DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
- dc.DrawBitmap(m_bmpFrameButtons[idx], r.x+1, r.y+1, TRUE);
- }
- else
- {
- DrawShadedRect(dc, &r, m_penHighlight, m_penBlack);
- DrawShadedRect(dc, &r, m_penLightGrey, m_penDarkGrey);
- DrawBackground(dc, wxSCHEME_COLOUR(m_scheme, CONTROL), r);
- dc.DrawBitmap(m_bmpFrameButtons[idx], r.x, r.y, TRUE);
- }
-}
-
-
-wxRect wxMetalRenderer::GetFrameClientArea(const wxRect& rect,
- int flags) const
-{
- wxRect r(rect);
-
- if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
- {
- int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
- RESIZEABLE_FRAME_BORDER_THICKNESS :
- FRAME_BORDER_THICKNESS;
- r.Inflate(-border);
- }
- if ( flags & wxTOPLEVEL_TITLEBAR )
- {
- r.y += FRAME_TITLEBAR_HEIGHT;
- r.height -= FRAME_TITLEBAR_HEIGHT;
- }
-
- return r;
-}
-
-wxSize wxMetalRenderer::GetFrameTotalSize(const wxSize& clientSize,
- int flags) const
-{
- wxSize s(clientSize);
-
- if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
- {
- int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
- RESIZEABLE_FRAME_BORDER_THICKNESS :
- FRAME_BORDER_THICKNESS;
- s.x += 2*border;
- s.y += 2*border;
- }
- if ( flags & wxTOPLEVEL_TITLEBAR )
- s.y += FRAME_TITLEBAR_HEIGHT;
-
- return s;
-}
-
-wxSize wxMetalRenderer::GetFrameMinSize(int flags) const
-{
- wxSize s(0, 0);
-
- if ( (flags & wxTOPLEVEL_BORDER) && !(flags & wxTOPLEVEL_MAXIMIZED) )
- {
- int border = (flags & wxTOPLEVEL_RESIZEABLE) ?
- RESIZEABLE_FRAME_BORDER_THICKNESS :
- FRAME_BORDER_THICKNESS;
- s.x += 2*border;
- s.y += 2*border;
- }
-
- if ( flags & wxTOPLEVEL_TITLEBAR )
- {
- s.y += FRAME_TITLEBAR_HEIGHT;
-
- if ( flags & wxTOPLEVEL_ICON )
- s.x += FRAME_TITLEBAR_HEIGHT + 2;
- if ( flags & wxTOPLEVEL_BUTTON_CLOSE )
- s.x += FRAME_BUTTON_WIDTH + 2;
- if ( flags & wxTOPLEVEL_BUTTON_MAXIMIZE )
- s.x += FRAME_BUTTON_WIDTH;
- if ( flags & wxTOPLEVEL_BUTTON_RESTORE )
- s.x += FRAME_BUTTON_WIDTH;
- if ( flags & wxTOPLEVEL_BUTTON_ICONIZE )
- s.x += FRAME_BUTTON_WIDTH;
- if ( flags & wxTOPLEVEL_BUTTON_HELP )
- s.x += FRAME_BUTTON_WIDTH;
- }
-
- return s;
-}
-
-wxSize wxMetalRenderer::GetFrameIconSize() const
-{
- return wxSize(16, 16);
-}
-
-
-// ----------------------------------------------------------------------------
-// standard icons
-// ----------------------------------------------------------------------------
-
-static char *error_xpm[]={
-"32 32 5 1",
-". c None",
-"# c #800000",
-"b c #808080",
-"a c #ff0000",
-"c c #ffffff",
-"...........########.............",
-"........###aaaaaaaa###..........",
-".......#aaaaaaaaaaaaaa#.........",
-".....##aaaaaaaaaaaaaaaa##.......",
-"....#aaaaaaaaaaaaaaaaaaaa#......",
-"...#aaaaaaaaaaaaaaaaaaaaaa#.....",
-"...#aaaaaaaaaaaaaaaaaaaaaa#b....",
-"..#aaaaaacaaaaaaaaaacaaaaaa#b...",
-".#aaaaaacccaaaaaaaacccaaaaaa#...",
-".#aaaaacccccaaaaaacccccaaaaa#b..",
-".#aaaaaacccccaaaacccccaaaaaa#bb.",
-"#aaaaaaaacccccaacccccaaaaaaaa#b.",
-"#aaaaaaaaaccccccccccaaaaaaaaa#b.",
-"#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
-"#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
-"#aaaaaaaaaaaccccccaaaaaaaaaaa#bb",
-"#aaaaaaaaaaccccccccaaaaaaaaaa#bb",
-"#aaaaaaaaaccccccccccaaaaaaaaa#bb",
-"#aaaaaaaacccccaacccccaaaaaaaa#bb",
-".#aaaaaacccccaaaacccccaaaaaa#bbb",
-".#aaaaacccccaaaaaacccccaaaaa#bbb",
-".#aaaaaacccaaaaaaaacccaaaaaa#bb.",
-"..#aaaaaacaaaaaaaaaacaaaaaa#bbb.",
-"...#aaaaaaaaaaaaaaaaaaaaaa#bbbb.",
-"...#aaaaaaaaaaaaaaaaaaaaaa#bbb..",
-"....#aaaaaaaaaaaaaaaaaaaa#bbb...",
-".....##aaaaaaaaaaaaaaaa##bbbb...",
-"......b#aaaaaaaaaaaaaa#bbbbb....",
-".......b###aaaaaaaa###bbbbb.....",
-".........bb########bbbbbb.......",
-"..........bbbbbbbbbbbbbb........",
-".............bbbbbbbb..........."};
-
-static char *info_xpm[]={
-"32 32 6 1",
-". c None",
-"d c #000000",
-"c c #0000ff",
-"# c #808080",
-"a c #c0c0c0",
-"b c #ffffff",
-"...........########.............",
-"........###abbbbbba###..........",
-"......##abbbbbbbbbbbba##........",
-".....#abbbbbbbbbbbbbbbba#.......",
-"....#bbbbbbbaccccabbbbbbbd......",
-"...#bbbbbbbbccccccbbbbbbbbd.....",
-"..#bbbbbbbbbccccccbbbbbbbbbd....",
-".#abbbbbbbbbaccccabbbbbbbbbad...",
-".#bbbbbbbbbbbbbbbbbbbbbbbbbbd#..",
-"#abbbbbbbbbbbbbbbbbbbbbbbbbbad#.",
-"#bbbbbbbbbbcccccccbbbbbbbbbbbd#.",
-"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
-"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
-"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
-"#bbbbbbbbbbbbcccccbbbbbbbbbbbd##",
-"#abbbbbbbbbbbcccccbbbbbbbbbbad##",
-".#bbbbbbbbbbbcccccbbbbbbbbbbd###",
-".#abbbbbbbbbbcccccbbbbbbbbbad###",
-"..#bbbbbbbbcccccccccbbbbbbbd###.",
-"...dbbbbbbbbbbbbbbbbbbbbbbd####.",
-"....dbbbbbbbbbbbbbbbbbbbbd####..",
-".....dabbbbbbbbbbbbbbbbad####...",
-"......ddabbbbbbbbbbbbadd####....",
-".......#dddabbbbbbaddd#####.....",
-"........###dddabbbd#######......",
-"..........####dbbbd#####........",
-".............#dbbbd##...........",
-"...............dbbd##...........",
-"................dbd##...........",
-".................dd##...........",
-"..................###...........",
-"...................##..........."};
-
-static char *question_xpm[]={
-"32 32 6 1",
-". c None",
-"c c #000000",
-"d c #0000ff",
-"# c #808080",
-"a c #c0c0c0",
-"b c #ffffff",
-"...........########.............",
-"........###abbbbbba###..........",
-"......##abbbbbbbbbbbba##........",
-".....#abbbbbbbbbbbbbbbba#.......",
-"....#bbbbbbbbbbbbbbbbbbbbc......",
-"...#bbbbbbbaddddddabbbbbbbc.....",
-"..#bbbbbbbadabbddddabbbbbbbc....",
-".#abbbbbbbddbbbbddddbbbbbbbac...",
-".#bbbbbbbbddddbbddddbbbbbbbbc#..",
-"#abbbbbbbbddddbaddddbbbbbbbbac#.",
-"#bbbbbbbbbaddabddddbbbbbbbbbbc#.",
-"#bbbbbbbbbbbbbadddbbbbbbbbbbbc##",
-"#bbbbbbbbbbbbbdddbbbbbbbbbbbbc##",
-"#bbbbbbbbbbbbbddabbbbbbbbbbbbc##",
-"#bbbbbbbbbbbbbddbbbbbbbbbbbbbc##",
-"#abbbbbbbbbbbbbbbbbbbbbbbbbbac##",
-".#bbbbbbbbbbbaddabbbbbbbbbbbc###",
-".#abbbbbbbbbbddddbbbbbbbbbbac###",
-"..#bbbbbbbbbbddddbbbbbbbbbbc###.",
-"...cbbbbbbbbbaddabbbbbbbbbc####.",
-"....cbbbbbbbbbbbbbbbbbbbbc####..",
-".....cabbbbbbbbbbbbbbbbac####...",
-"......ccabbbbbbbbbbbbacc####....",
-".......#cccabbbbbbaccc#####.....",
-"........###cccabbbc#######......",
-"..........####cbbbc#####........",
-".............#cbbbc##...........",
-"...............cbbc##...........",
-"................cbc##...........",
-".................cc##...........",
-"..................###...........",
-"...................##..........."};
-
-static char *warning_xpm[]={
-"32 32 6 1",
-". c None",
-"c c #000000",
-"# c #808000",
-"d c #808080",
-"b c #c0c0c0",
-"a c #ffff00",
-".............###................",
-"............#aabc...............",
-"...........#aaaabcd.............",
-"...........#aaaaacdd............",
-"..........#aaaaaabcdd...........",
-"..........#aaaaaaacdd...........",
-".........#aaaaaaaabcdd..........",
-".........#aaaaaaaaacdd..........",
-"........#aaaaaaaaaabcdd.........",
-"........#aaabcccbaaacdd.........",
-".......#aaaacccccaaabcdd........",
-".......#aaaacccccaaaacdd........",
-"......#aaaaacccccaaaabcdd.......",
-"......#aaaaacccccaaaaacdd.......",
-".....#aaaaaacccccaaaaabcdd......",
-".....#aaaaaa#ccc#aaaaaacdd......",
-"....#aaaaaaabcccbaaaaaabcdd.....",
-"....#aaaaaaaacccaaaaaaaacdd.....",
-"...#aaaaaaaaa#c#aaaaaaaabcdd....",
-"...#aaaaaaaaabcbaaaaaaaaacdd....",
-"..#aaaaaaaaaaacaaaaaaaaaabcdd...",
-"..#aaaaaaaaaaaaaaaaaaaaaaacdd...",
-".#aaaaaaaaaaabccbaaaaaaaaabcdd..",
-".#aaaaaaaaaaaccccaaaaaaaaaacdd..",
-"#aaaaaaaaaaaaccccaaaaaaaaaabcdd.",
-"#aaaaaaaaaaaabccbaaaaaaaaaaacdd.",
-"#aaaaaaaaaaaaaaaaaaaaaaaaaaacddd",
-"#aaaaaaaaaaaaaaaaaaaaaaaaaabcddd",
-".#aaaaaaaaaaaaaaaaaaaaaaaabcdddd",
-"..#ccccccccccccccccccccccccddddd",
-"....ddddddddddddddddddddddddddd.",
-".....ddddddddddddddddddddddddd.."};
-
-wxBitmap wxMetalArtProvider::CreateBitmap(const wxArtID& id,
- const wxArtClient& WXUNUSED(client),
- const wxSize& WXUNUSED(size))
-{
- 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;
-}
-
-
-// ----------------------------------------------------------------------------
-// text control geometry
-// ----------------------------------------------------------------------------
-
-static inline int GetTextBorderWidth()
-{
- return 1;
-}
-
-wxRect wxMetalRenderer::GetTextTotalArea(const wxTextCtrl *text,
- const wxRect& rect) const
-{
- wxRect rectTotal = rect;
-
- wxCoord widthBorder = GetTextBorderWidth();
- rectTotal.Inflate(widthBorder);
-
- // this is what Windows does
- rectTotal.height++;
-
- return rectTotal;
-}
-
-wxRect wxMetalRenderer::GetTextClientArea(const wxTextCtrl *text,
- const wxRect& rect,
- wxCoord *extraSpaceBeyond) const
-{
- wxRect rectText = rect;
-
- // undo GetTextTotalArea()
- if ( rectText.height > 0 )
- rectText.height--;
-
- wxCoord widthBorder = GetTextBorderWidth();
- rectText.Inflate(-widthBorder);
-
- if ( extraSpaceBeyond )
- *extraSpaceBeyond = 0;
-
- return rectText;
-}
-
-// ----------------------------------------------------------------------------
-// size adjustments
-// ----------------------------------------------------------------------------
-
-void wxMetalRenderer::AdjustSize(wxSize *size, const wxWindow *window)
-{
-#if wxUSE_SCROLLBAR
- if ( wxDynamicCast(window, wxScrollBar) )
- {
- // we only set the width of vert scrollbars and height of the
- // horizontal ones
- if ( window->GetWindowStyle() & wxSB_HORIZONTAL )
- size->y = m_sizeScrollbarArrow.y;
- else
- size->x = m_sizeScrollbarArrow.x;
-
- // skip border width adjustments, they don't make sense for us
- return;
- }
-#endif // wxUSE_SCROLLBAR/!wxUSE_SCROLLBAR
-
-#if wxUSE_BUTTON
- if ( wxDynamicCast(window, wxButton) )
- {
- if ( !(window->GetWindowStyle() & wxBU_EXACTFIT) )
- {
- // TODO: don't harcode all this
- size->x += 3*window->GetCharWidth();
-
- wxCoord heightBtn = (11*(window->GetCharHeight() + 8))/10;
- if ( size->y < heightBtn - 8 )
- size->y = heightBtn;
- else
- size->y += 9;
- }
-
- // no border width adjustments for buttons
- return;
- }
-#endif // wxUSE_BUTTON
-
- // take into account the border width
- wxRect rectBorder = GetBorderDimensions(window->GetBorder());
- size->x += rectBorder.x + rectBorder.width;
- size->y += rectBorder.y + rectBorder.height;
-}
-
-// ============================================================================
-// wxInputHandler
-// ============================================================================
-
-// ----------------------------------------------------------------------------
-// wxMetalInputHandler
-// ----------------------------------------------------------------------------
-
-wxMetalInputHandler::wxMetalInputHandler(wxMetalRenderer *renderer)
-{
- m_renderer = renderer;
-}
-
-bool wxMetalInputHandler::HandleKey(wxInputConsumer *control,
- const wxKeyEvent& event,
- bool pressed)
-{
- return FALSE;
-}
-
-bool wxMetalInputHandler::HandleMouse(wxInputConsumer *control,
- const wxMouseEvent& event)
-{
- // clicking on the control gives it focus
- if ( event.ButtonDown() )
- {
- wxWindow *win = control->GetInputWindow();
-
- if (( wxWindow::FindFocus() != control->GetInputWindow() ) &&
- ( win->AcceptsFocus() ) )
- {
- win->SetFocus();
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-// ----------------------------------------------------------------------------
-// wxMetalScrollBarInputHandler
-// ----------------------------------------------------------------------------
-
-wxMetalScrollBarInputHandler::
-wxMetalScrollBarInputHandler(wxMetalRenderer *renderer,
- wxInputHandler *handler)
- : wxStdScrollBarInputHandler(renderer, handler)
-{
- m_scrollPaused = FALSE;
- m_interval = 0;
-}
-
-bool wxMetalScrollBarInputHandler::OnScrollTimer(wxScrollBar *scrollbar,
- const wxControlAction& action)
-{
- // stop if went beyond the position of the original click (this can only
- // happen when we scroll by pages)
- bool stop = FALSE;
- if ( action == wxACTION_SCROLL_PAGE_DOWN )
- {
- stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
- != wxHT_SCROLLBAR_BAR_2;
- }
- else if ( action == wxACTION_SCROLL_PAGE_UP )
- {
- stop = m_renderer->HitTestScrollbar(scrollbar, m_ptStartScrolling)
- != wxHT_SCROLLBAR_BAR_1;
- }
-
- if ( stop )
- {
- StopScrolling(scrollbar);
-
- scrollbar->Refresh();
-
- return FALSE;
- }
-
- return wxStdScrollBarInputHandler::OnScrollTimer(scrollbar, action);
-}
-
-bool wxMetalScrollBarInputHandler::HandleMouse(wxInputConsumer *control,
- const wxMouseEvent& event)
-{
- // remember the current state
- bool wasDraggingThumb = m_htLast == wxHT_SCROLLBAR_THUMB;
-
- // do process the message
- bool rc = wxStdScrollBarInputHandler::HandleMouse(control, event);
-
- // analyse the changes
- if ( !wasDraggingThumb && (m_htLast == wxHT_SCROLLBAR_THUMB) )
- {
- // we just started dragging the thumb, remember its initial position to
- // be able to restore it if the drag is cancelled later
- m_eventStartDrag = event;
- }
-
- return rc;
-}
-
-bool wxMetalScrollBarInputHandler::HandleMouseMove(wxInputConsumer *control,
- const wxMouseEvent& event)
-{
- // we don't highlight scrollbar elements, so there is no need to process
- // mouse move events normally - only do it while mouse is captured (i.e.
- // when we're dragging the thumb or pressing on something)
- if ( !m_winCapture )
- return FALSE;
-
- if ( event.Entering() )
- {
- // we're not interested in this at all
- return FALSE;
- }
-
- wxScrollBar *scrollbar = wxStaticCast(control->GetInputWindow(), wxScrollBar);
- wxHitTest ht;
- if ( m_scrollPaused )
- {
- // check if the mouse returned to its original location
-
- if ( event.Leaving() )
- {
- // it surely didn't
- return FALSE;
- }
-
- ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
- if ( ht == m_htLast )
- {
- // yes it did, resume scrolling
- m_scrollPaused = FALSE;
- if ( m_timerScroll )
- {
- // we were scrolling by line/page, restart timer
- m_timerScroll->Start(m_interval);
-
- Press(scrollbar, TRUE);
- }
- else // we were dragging the thumb
- {
- // restore its last location
- HandleThumbMove(scrollbar, m_eventLastDrag);
- }
-
- return TRUE;
- }
- }
- else // normal case, scrolling hasn't been paused
- {
- // if we're scrolling the scrollbar because the arrow or the shaft was
- // pressed, check that the mouse stays on the same scrollbar element
-
-#if 0
- // Always let thumb jump back if we leave the scrollbar
- if ( event.Moving() )
- {
- ht = m_renderer->HitTestScrollbar(scrollbar, event.GetPosition());
- }
- else // event.Leaving()
- {
- ht = wxHT_NOWHERE;
- }
-#else
- // Jump back only if we get far away from it
- wxPoint pos = event.GetPosition();
- if (scrollbar->HasFlag( wxVERTICAL ))
- {
- if (pos.x > -40 && pos.x < scrollbar->GetSize().x+40)
- pos.x = 5;
- }
- else
- {
- if (pos.y > -40 && pos.y < scrollbar->GetSize().y+40)
- pos.y = 5;
- }
- ht = m_renderer->HitTestScrollbar(scrollbar, pos );
-#endif
-
- // if we're dragging the thumb and the mouse stays in the scrollbar, it
- // is still ok - we only want to catch the case when the mouse leaves
- // the scrollbar here
- if ( m_htLast == wxHT_SCROLLBAR_THUMB && ht != wxHT_NOWHERE )
- {
- ht = wxHT_SCROLLBAR_THUMB;
- }
-
- if ( ht != m_htLast )
- {
- // what were we doing? 2 possibilities: either an arrow/shaft was
- // pressed in which case we have a timer and so we just stop it or
- // we were dragging the thumb
- if ( m_timerScroll )
- {
- // pause scrolling
- m_interval = m_timerScroll->GetInterval();
- m_timerScroll->Stop();
- m_scrollPaused = TRUE;
-
- // unpress the arrow
- Press(scrollbar, FALSE);
- }
- else // we were dragging the thumb
- {
- // remember the current thumb position to be able to restore it
- // if the mouse returns to it later
- m_eventLastDrag = event;
-
- // and restore the original position (before dragging) of the
- // thumb for now
- HandleThumbMove(scrollbar, m_eventStartDrag);
- }
-
- return TRUE;
- }
- }
-
- return wxStdScrollBarInputHandler::HandleMouseMove(control, event);
-}
-
-// ----------------------------------------------------------------------------
-// wxMetalCheckboxInputHandler
-// ----------------------------------------------------------------------------
-
-bool wxMetalCheckboxInputHandler::HandleKey(wxInputConsumer *control,
- const wxKeyEvent& event,
- bool pressed)
-{
- if ( pressed )
- {
- wxControlAction action;
- int keycode = event.GetKeyCode();
- switch ( keycode )
- {
- case WXK_SPACE:
- action = wxACTION_CHECKBOX_TOGGLE;
- break;
-
- case WXK_SUBTRACT:
- case WXK_NUMPAD_SUBTRACT:
- action = wxACTION_CHECKBOX_CHECK;
- break;
-
- case WXK_ADD:
- case WXK_NUMPAD_ADD:
- case WXK_NUMPAD_EQUAL:
- action = wxACTION_CHECKBOX_CLEAR;
- break;
- }
-
- if ( !!action )
- {
- control->PerformAction(action);
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-// ----------------------------------------------------------------------------
-// wxMetalTextCtrlInputHandler
-// ----------------------------------------------------------------------------
-
-bool wxMetalTextCtrlInputHandler::HandleKey(wxInputConsumer *control,
- const wxKeyEvent& event,
- bool pressed)
-{
- // handle only MSW-specific text bindings here, the others are handled in
- // the base class
- if ( pressed )
- {
- int keycode = event.GetKeyCode();
-
- wxControlAction action;
- if ( keycode == WXK_DELETE && event.ShiftDown() )
- {
- action = wxACTION_TEXT_CUT;
- }
- else if ( keycode == WXK_INSERT )
- {
- if ( event.ControlDown() )
- action = wxACTION_TEXT_COPY;
- else if ( event.ShiftDown() )
- action = wxACTION_TEXT_PASTE;
- }
-
- if ( action != wxACTION_NONE )
- {
- control->PerformAction(action);
-
- return TRUE;
- }
- }
-
- return wxStdTextCtrlInputHandler::HandleKey(control, event, pressed);
-}
-
-// ----------------------------------------------------------------------------
-// wxMetalStatusBarInputHandler
-// ----------------------------------------------------------------------------
-
-wxMetalStatusBarInputHandler::
-wxMetalStatusBarInputHandler(wxInputHandler *handler)
- : wxStdInputHandler(handler)
-{
- m_isOnGrip = FALSE;
-}
-
-bool wxMetalStatusBarInputHandler::IsOnGrip(wxWindow *statbar,
- const wxPoint& pt) const
-{
- if ( statbar->HasFlag(wxST_SIZEGRIP) &&
- statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
- {
- wxTopLevelWindow *
- parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow);
-
- wxCHECK_MSG( parentTLW, FALSE,
- _T("the status bar should be a child of a TLW") );
-
- // a maximized window can't be resized anyhow
- if ( !parentTLW->IsMaximized() )
- {
- // VZ: I think that the standard Windows behaviour is to only
- // show the resizing cursor when the mouse is on top of the
- // grip itself but apparently different Windows versions behave
- // differently (?) and it seems a better UI to allow resizing
- // the status bar even when the mouse is above the grip
- wxSize sizeSbar = statbar->GetSize();
-
- int diff = sizeSbar.x - pt.x;
- return diff >= 0 && diff < (wxCoord)STATUSBAR_GRIP_SIZE;
- }
- }
-
- return FALSE;
-}
-
-bool wxMetalStatusBarInputHandler::HandleMouse(wxInputConsumer *consumer,
- const wxMouseEvent& event)
-{
- if ( event.Button(1) )
- {
- if ( event.ButtonDown(1) )
- {
- wxWindow *statbar = consumer->GetInputWindow();
-
- if ( IsOnGrip(statbar, event.GetPosition()) )
- {
- wxTopLevelWindow *tlw = wxDynamicCast(statbar->GetParent(),
- wxTopLevelWindow);
- if ( tlw )
- {
- tlw->PerformAction(wxACTION_TOPLEVEL_RESIZE,
- wxHT_TOPLEVEL_BORDER_SE);
-
- statbar->SetCursor(m_cursorOld);
-
- return TRUE;
- }
- }
- }
- }
-
- return wxStdInputHandler::HandleMouse(consumer, event);
-}
-
-bool wxMetalStatusBarInputHandler::HandleMouseMove(wxInputConsumer *consumer,
- const wxMouseEvent& event)
-{
- wxWindow *statbar = consumer->GetInputWindow();
-
- bool isOnGrip = IsOnGrip(statbar, event.GetPosition());
- if ( isOnGrip != m_isOnGrip )
- {
- m_isOnGrip = isOnGrip;
- if ( isOnGrip )
- {
- m_cursorOld = statbar->GetCursor();
- statbar->SetCursor(wxCURSOR_SIZENWSE);
- }
- else
- {
- statbar->SetCursor(m_cursorOld);
- }
- }
-
- return wxStdInputHandler::HandleMouseMove(consumer, event);
-}
-
-// ----------------------------------------------------------------------------
-// wxMetalFrameInputHandler
-// ----------------------------------------------------------------------------
-
-class wxMetalSystemMenuEvtHandler : public wxEvtHandler
-{
-public:
- wxMetalSystemMenuEvtHandler(wxMetalFrameInputHandler *handler);
-
- void Attach(wxInputConsumer *consumer);
- void Detach();
-
-private:
- DECLARE_EVENT_TABLE()
- void OnSystemMenu(wxCommandEvent &event);
- void OnCloseFrame(wxCommandEvent &event);
- void OnClose(wxCloseEvent &event);
-
- wxMetalFrameInputHandler *m_inputHnd;
- wxTopLevelWindow *m_wnd;
- wxAcceleratorTable m_oldAccelTable;
-};
-
-wxMetalSystemMenuEvtHandler::wxMetalSystemMenuEvtHandler(
- wxMetalFrameInputHandler *handler)
-{
- m_inputHnd = handler;
- m_wnd = NULL;
-}
-
-void wxMetalSystemMenuEvtHandler::Attach(wxInputConsumer *consumer)
-{
- wxASSERT_MSG( m_wnd == NULL, _T("can't attach the handler twice!") );
-
- m_wnd = wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
- m_wnd->PushEventHandler(this);
-
- // VS: This code relies on using generic implementation of
- // wxAcceleratorTable in wxUniv!
- wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
- m_oldAccelTable = table;
- table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_SPACE, wxID_SYSTEM_MENU));
- table.Add(wxAcceleratorEntry(wxACCEL_ALT, WXK_F4, wxID_CLOSE_FRAME));
- m_wnd->SetAcceleratorTable(table);
-}
-
-void wxMetalSystemMenuEvtHandler::Detach()
-{
- if ( m_wnd )
- {
- m_wnd->SetAcceleratorTable(m_oldAccelTable);
- m_wnd->RemoveEventHandler(this);
- m_wnd = NULL;
- }
-}
-
-BEGIN_EVENT_TABLE(wxMetalSystemMenuEvtHandler, wxEvtHandler)
- EVT_MENU(wxID_SYSTEM_MENU, wxMetalSystemMenuEvtHandler::OnSystemMenu)
- EVT_MENU(wxID_CLOSE_FRAME, wxMetalSystemMenuEvtHandler::OnCloseFrame)
- EVT_CLOSE(wxMetalSystemMenuEvtHandler::OnClose)
-END_EVENT_TABLE()
-
-void wxMetalSystemMenuEvtHandler::OnSystemMenu(wxCommandEvent &WXUNUSED(event))
-{
- int border = ((m_wnd->GetWindowStyle() & wxRESIZE_BORDER) &&
- !m_wnd->IsMaximized()) ?
- RESIZEABLE_FRAME_BORDER_THICKNESS :
- FRAME_BORDER_THICKNESS;
- wxPoint pt = m_wnd->GetClientAreaOrigin();
- pt.x = -pt.x + border;
- pt.y = -pt.y + border + FRAME_TITLEBAR_HEIGHT;
-
- wxAcceleratorTable table = *m_wnd->GetAcceleratorTable();
- m_wnd->SetAcceleratorTable(wxNullAcceleratorTable);
- m_inputHnd->PopupSystemMenu(m_wnd, pt);
- m_wnd->SetAcceleratorTable(table);
-}
-
-void wxMetalSystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
-{
- m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
- wxTOPLEVEL_BUTTON_CLOSE);
-}
-
-void wxMetalSystemMenuEvtHandler::OnClose(wxCloseEvent &event)
-{
- m_wnd = NULL;
- event.Skip();
-}
-
-
-wxMetalFrameInputHandler::wxMetalFrameInputHandler(wxInputHandler *handler)
- : wxStdFrameInputHandler(handler)
-{
- m_menuHandler = new wxMetalSystemMenuEvtHandler(this);
-}
-
-wxMetalFrameInputHandler::~wxMetalFrameInputHandler()
-{
- if ( m_menuHandler )
- {
- m_menuHandler->Detach();
- delete m_menuHandler;
- }
-}
-
-bool wxMetalFrameInputHandler::HandleMouse(wxInputConsumer *consumer,
- const wxMouseEvent& event)
-{
- if ( event.LeftDClick() || event.LeftDown() || event.RightDown() )
- {
- wxTopLevelWindow *tlw =
- wxStaticCast(consumer->GetInputWindow(), wxTopLevelWindow);
-
- long hit = tlw->HitTest(event.GetPosition());
-
- if ( event.LeftDClick() && hit == wxHT_TOPLEVEL_TITLEBAR )
- {
- tlw->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
- tlw->IsMaximized() ? wxTOPLEVEL_BUTTON_RESTORE
- : wxTOPLEVEL_BUTTON_MAXIMIZE);
- return TRUE;
- }
- else if ( tlw->GetWindowStyle() & wxSYSTEM_MENU )
- {
- if ( (event.LeftDown() && hit == wxHT_TOPLEVEL_ICON) ||
- (event.RightDown() &&
- (hit == wxHT_TOPLEVEL_TITLEBAR ||
- hit == wxHT_TOPLEVEL_ICON)) )
- {
- PopupSystemMenu(tlw, event.GetPosition());
- return TRUE;
- }
- }
- }
-
- return wxStdFrameInputHandler::HandleMouse(consumer, event);
-}
-
-void wxMetalFrameInputHandler::PopupSystemMenu(wxTopLevelWindow *window,
- const wxPoint& pos) const
-{
- wxMenu *menu = new wxMenu;
-
- if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
- menu->Append(wxID_RESTORE_FRAME , _("&Restore"));
- menu->Append(wxID_MOVE_FRAME , _("&Move"));
- if ( window->GetWindowStyle() & wxRESIZE_BORDER )
- menu->Append(wxID_RESIZE_FRAME , _("&Size"));
- if ( wxSystemSettings::HasFeature(wxSYS_CAN_ICONIZE_FRAME) )
- menu->Append(wxID_ICONIZE_FRAME , _("Mi&nimize"));
- if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
- menu->Append(wxID_MAXIMIZE_FRAME , _("Ma&ximize"));
- menu->AppendSeparator();
- menu->Append(wxID_CLOSE_FRAME, _("Close\tAlt-F4"));
-
- if ( window->GetWindowStyle() & wxMAXIMIZE_BOX )
- {
- if ( window->IsMaximized() )
- {
- menu->Enable(wxID_MAXIMIZE_FRAME, FALSE);
- menu->Enable(wxID_MOVE_FRAME, FALSE);
- if ( window->GetWindowStyle() & wxRESIZE_BORDER )
- menu->Enable(wxID_RESIZE_FRAME, FALSE);
- }
- else
- menu->Enable(wxID_RESTORE_FRAME, FALSE);
- }
-
- window->PopupMenu(menu, pos);
- delete menu;
-}
-
-bool wxMetalFrameInputHandler::HandleActivation(wxInputConsumer *consumer,
- bool activated)
-{
- if ( consumer->GetInputWindow()->GetWindowStyle() & wxSYSTEM_MENU )
- {
- // always detach if active frame changed:
- m_menuHandler->Detach();
-
- if ( activated )
- {
- m_menuHandler->Attach(consumer);
- }
- }
-
- return wxStdFrameInputHandler::HandleActivation(consumer, activated);
-}