#include "wx/scrolbar.h"
#include "wx/slider.h"
#include "wx/textctrl.h"
+ #include "wx/toolbar.h"
#ifdef __WXMSW__
// for COLOR_* constants
#include "wx/spinbutt.h"
#include "wx/settings.h"
#include "wx/menu.h"
+#include "wx/artprov.h"
+#include "wx/toplevel.h"
#include "wx/univ/scrtimer.h"
-#include "wx/toplevel.h"
#include "wx/univ/renderer.h"
#include "wx/univ/inphand.h"
#include "wx/univ/colschem.h"
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,
int flags = 0,
wxAlignment align = wxALIGN_LEFT,
int indexAccel = -1);
+ virtual void DrawToolBarButton(wxDC& dc,
+ const wxString& label,
+ const wxBitmap& bitmap,
+ const wxRect& rect,
+ int flags);
virtual void DrawTextLine(wxDC& dc,
const wxString& text,
const wxRect& rect,
int flags = 0);
virtual wxRect GetFrameClientArea(const wxRect& rect, int flags) const;
virtual wxSize GetFrameTotalSize(const wxSize& clientSize, int flags) const;
+ 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,
wxBitmap *bmpPressed,
virtual wxCoord GetCheckItemMargin() const
{ return 0; }
+ virtual wxSize GetToolBarButtonSize(wxCoord *separator) const
+ { if ( separator ) *separator = 5; return wxSize(16, 15); }
+ virtual wxSize GetToolBarMargin() const
+ { return wxSize(4, 4); }
+
virtual wxRect GetTextTotalArea(const wxTextCtrl *text,
- const wxRect& rect);
+ const wxRect& rect) const;
virtual wxRect GetTextClientArea(const wxTextCtrl *text,
const wxRect& rect,
- wxCoord *extraSpaceBeyond);
+ wxCoord *extraSpaceBeyond) const;
virtual wxSize GetTabIndent() const { return wxSize(2, 2); }
virtual wxSize GetTabPadding() const { return wxSize(6, 5); }
// DrawButtonBorder() helper
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
wxFont m_titlebarFont;
+ // the checked and unchecked bitmaps for DrawCheckItem()
+ wxBitmap m_bmpCheckBitmaps[IndicatorStatus_Max];
+
+ // the bitmaps returned by GetIndicator()
+ wxBitmap m_bmpIndicators[IndicatorType_Max]
+ [IndicatorState_Max]
+ [IndicatorStatus_Max];
+
// titlebar icons:
wxBitmap m_bmpFrameButtons[FrameButton_Max];
bool m_isOnGrip;
};
+class wxWin32SystemMenuEvtHandler;
+
+class wxWin32FrameInputHandler : public wxStdFrameInputHandler
+{
+public:
+ wxWin32FrameInputHandler(wxInputHandler *handler);
+ ~wxWin32FrameInputHandler();
+
+ virtual bool HandleMouse(wxInputConsumer *control,
+ const wxMouseEvent& event);
+
+ virtual bool HandleActivation(wxInputConsumer *consumer, bool activated);
+
+ void PopupSystemMenu(wxTopLevelWindow *window, const wxPoint& pos) const;
+
+private:
+ // was the mouse over the grip last time we checked?
+ wxWin32SystemMenuEvtHandler *m_menuHandler;
+};
+
// ----------------------------------------------------------------------------
// wxWin32ColourScheme: uses (default) Win32 colours
// ----------------------------------------------------------------------------
virtual wxColour GetBackground(wxWindow *win) const;
};
+// ----------------------------------------------------------------------------
+// wxWin32ArtProvider
+// ----------------------------------------------------------------------------
+
+class wxWin32ArtProvider : public wxArtProvider
+{
+protected:
+ virtual wxBitmap CreateBitmap(const wxArtID& id,
+ const wxArtClient& client,
+ const wxSize& size);
+};
+
// ----------------------------------------------------------------------------
// wxWin32Theme
// ----------------------------------------------------------------------------
virtual ~wxWin32Theme();
virtual wxRenderer *GetRenderer();
+ virtual wxArtProvider *GetArtProvider();
virtual wxInputHandler *GetInputHandler(const wxString& control);
virtual wxColourScheme *GetColourScheme();
wxInputHandler *GetDefaultInputHandler();
wxWin32Renderer *m_renderer;
+
+ wxWin32ArtProvider *m_artProvider;
// the names of the already created handlers and the handlers themselves
// (these arrays are synchronized)
static const char *frame_button_close_xpm[] = {
"12 10 2 1",
-" c None",
-". c black",
+" c None",
+". c black",
" ",
" .. .. ",
" .. .. ",
static const char *frame_button_help_xpm[] = {
"12 10 2 1",
-" c None",
-". c #000000",
+" c None",
+". c #000000",
" .... ",
" .. .. ",
" .. .. ",
static const char *frame_button_maximize_xpm[] = {
"12 10 2 1",
-" c None",
-". c #000000",
+" c None",
+". c #000000",
" ......... ",
" ......... ",
" . . ",
static const char *frame_button_minimize_xpm[] = {
"12 10 2 1",
-" c None",
-". c #000000",
+" c None",
+". c #000000",
" ",
" ",
" ",
static const char *frame_button_restore_xpm[] = {
"12 10 2 1",
-" c None",
-". c #000000",
+" c None",
+". c #000000",
" ...... ",
" ...... ",
" . . ",
};
static const char **
- bmpIndicators[IndicatorType_Max][IndicatorState_Max][IndicatorStatus_Max] =
+ xpmIndicators[IndicatorType_Max][IndicatorState_Max][IndicatorStatus_Max] =
{
// checkboxes first
{
}
};
+static const char **xpmChecked[IndicatorStatus_Max] =
+{
+ checked_item_xpm,
+ unchecked_item_xpm
+};
+
// ============================================================================
// implementation
// ============================================================================
m_scheme = NULL;
m_renderer = NULL;
m_handlerDefault = NULL;
+ m_artProvider = NULL;
}
wxWin32Theme::~wxWin32Theme()
delete m_renderer;
delete m_scheme;
+ wxArtProvider::RemoveProvider(m_artProvider);
}
wxRenderer *wxWin32Theme::GetRenderer()
return m_renderer;
}
+wxArtProvider *wxWin32Theme::GetArtProvider()
+{
+ if ( !m_artProvider )
+ {
+ m_artProvider = new wxWin32ArtProvider;
+ }
+
+ return m_artProvider;
+}
+
wxInputHandler *wxWin32Theme::GetDefaultInputHandler()
{
if ( !m_handlerDefault )
else if ( control == wxINP_HANDLER_STATUSBAR )
handler = new wxWin32StatusBarInputHandler(GetDefaultInputHandler());
#endif // wxUSE_STATUSBAR
+#if wxUSE_TOOLBAR
+ else if ( control == wxINP_HANDLER_TOOLBAR )
+ handler = new wxStdToolbarInputHandler(GetDefaultInputHandler());
+#endif // wxUSE_TOOLBAR
else if ( control == wxINP_HANDLER_TOPLEVEL )
- handler = new wxStdFrameInputHandler(GetDefaultInputHandler());
+ handler = new wxWin32FrameInputHandler(GetDefaultInputHandler());
else
handler = GetDefaultInputHandler();
// the colour set by the user should be used for the normal state
// and for the states for which we don't have any specific colours
- if ( !col.Ok() || (flags != 0) )
+ if ( !col.Ok() || (flags & wxCONTROL_PRESSED) != 0 )
{
if ( wxDynamicCast(win, wxScrollBar) )
col = Get(flags & wxCONTROL_PRESSED ? SCROLLBAR_PRESSED
case CONTROL_TEXT: return wxColour(GetSysColor(COLOR_BTNTEXT));
- case SCROLLBAR: return wxColour(GetSysColor(COLOR_SCROLLBAR));
- case SCROLLBAR_PRESSED: return wxColour(GetSysColor(COLOR_HIGHLIGHT));
+#if defined(COLOR_3DLIGHT)
+ case SCROLLBAR: return wxColour(GetSysColor(COLOR_3DLIGHT));
+#else
+ case SCROLLBAR: return wxColour(0xe0e0e0);
+#endif
+ case SCROLLBAR_PRESSED: return wxColour(GetSysColor(COLOR_BTNTEXT));
case HIGHLIGHT: return wxColour(GetSysColor(COLOR_HIGHLIGHT));
case HIGHLIGHT_TEXT: return wxColour(GetSysColor(COLOR_HIGHLIGHTTEXT));
#if defined(COLOR_3DDKSHADOW)
case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DDKSHADOW));
#else
- case SHADOW_DARK: return *wxBLACK;
+ case SHADOW_DARK: return wxColour(GetSysColor(COLOR_3DHADOW));
#endif
case CONTROL_TEXT_DISABLED:
case TITLEBAR_ACTIVE: return wxColour(GetSysColor(COLOR_ACTIVECAPTION));
case TITLEBAR_TEXT: return wxColour(GetSysColor(COLOR_INACTIVECAPTIONTEXT));
case TITLEBAR_ACTIVE_TEXT: return wxColour(GetSysColor(COLOR_CAPTIONTEXT));
-
+
case DESKTOP: return wxColour(0x808000);
#else // !__WXMSW__
// use the standard Windows colours elsewhere
case DESKTOP: return wxColour(0x808000);
#endif // __WXMSW__
+ case GAUGE: return Get(HIGHLIGHT);
+
case MAX:
default:
wxFAIL_MSG(_T("invalid standard colour"));
break;
default:
+ {
+ // char *crash = NULL;
+ // *crash = 0;
wxFAIL_MSG(_T("unknown border type"));
// fall through
+ }
case wxBORDER_DEFAULT:
case wxBORDER_NONE:
}
else // use default bitmap
{
- bmp = wxBitmap(flags & wxCONTROL_CHECKED ? checked_item_xpm
- : unchecked_item_xpm);
+ 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,
? IndicatorStatus_Checked
: IndicatorStatus_Unchecked;
- const char **xpm = bmpIndicators[indType][indState][indStatus];
- if (xpm)
+ wxBitmap bmp = m_bmpIndicators[indType][indState][indStatus];
+ if ( !bmp.Ok() )
{
- wxBitmap bmp(xpm);
- return bmp;
+ const char **xpm = xpmIndicators[indType][indState][indStatus];
+ if ( xpm )
+ {
+ // create and cache it
+ bmp = wxBitmap(xpm);
+ m_bmpIndicators[indType][indState][indStatus] = bmp;
+ }
}
- else
- return wxNullBitmap;
+
+ return bmp;
}
void wxWin32Renderer::DrawCheckOrRadioButton(wxDC& dc,
wxAlignment align,
int indexAccel)
{
- if (bitmap.Ok())
- DrawCheckOrRadioButton(dc, label,
- bitmap,
- rect, flags, align, indexAccel,
- FOCUS_RECT_OFFSET_Y); // default focus rect offset
+ wxBitmap bmp;
+ if ( bitmap.Ok() )
+ bmp = bitmap;
else
- {
- wxBitmap rbitmap(GetRadioBitmap(flags));
- DrawCheckOrRadioButton(dc, label,
- rbitmap,
+ bmp = GetRadioBitmap(flags);
+
+ DrawCheckOrRadioButton(dc, label,
+ bmp,
rect, flags, align, indexAccel,
- FOCUS_RECT_OFFSET_Y); // default focus rect offset
- }
+ FOCUS_RECT_OFFSET_Y); // default focus rect offset
}
void wxWin32Renderer::DrawCheckButton(wxDC& dc,
wxAlignment align,
int indexAccel)
{
- if (bitmap.Ok())
- DrawCheckOrRadioButton(dc, label,
- bitmap,
- rect, flags, align, indexAccel,
- 0); // no focus rect offset for checkboxes
+ 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 wxWin32Renderer::DrawToolBarButton(wxDC& dc,
+ const wxString& label,
+ const wxBitmap& bitmap,
+ const wxRect& rectOrig,
+ int flags)
+{
+ if ( !label.empty() || bitmap.Ok() )
{
- wxBitmap cbitmap(GetCheckBitmap(flags));
- DrawCheckOrRadioButton(dc, label,
- cbitmap,
- rect, flags, align, indexAccel,
- 0); // no focus rect offset for checkboxes
+ 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);
}
}
void wxWin32Renderer::DoDrawBackground(wxDC& dc,
const wxColour& col,
- const wxRect& rect)
+ const wxRect& rect,
+ wxWindow *window )
{
wxBrush brush(col, wxSOLID);
dc.SetBrush(brush);
void wxWin32Renderer::DrawBackground(wxDC& dc,
const wxColour& col,
const wxRect& rect,
- int flags)
+ int flags,
+ wxWindow *window )
{
// just fill it with the given or default bg colour
wxColour colBg = col.Ok() ? col : wxSCHEME_COLOUR(m_scheme, CONTROL);
- DoDrawBackground(dc, colBg, rect);
+ DoDrawBackground(dc, colBg, rect, window );
}
// ----------------------------------------------------------------------------
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);
- dc.DrawLabel(title, wxNullBitmap, r, wxALIGN_LEFT | wxALIGN_CENTRE_VERTICAL);
+
+ 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 wxWin32Renderer::DrawFrameIcon(wxDC& dc,
return s;
}
+wxSize wxWin32Renderer::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 wxWin32Renderer::GetFrameIconSize() const
{
return wxSize(16, 16);
"....ddddddddddddddddddddddddddd.",
".....ddddddddddddddddddddddddd.."};
-wxIcon wxWin32Renderer::GetStdIcon(int which) const
+wxBitmap wxWin32ArtProvider::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;
}
}
wxRect wxWin32Renderer::GetTextTotalArea(const wxTextCtrl *text,
- const wxRect& rect)
+ const wxRect& rect) const
{
wxRect rectTotal = rect;
wxRect wxWin32Renderer::GetTextClientArea(const wxTextCtrl *text,
const wxRect& rect,
- wxCoord *extraSpaceBeyond)
+ wxCoord *extraSpaceBeyond) const
{
wxRect rectText = rect;
if ( event.ButtonDown() )
{
wxWindow *win = control->GetInputWindow();
- if ( wxWindow::FindFocus() != control->GetInputWindow() )
+
+ if (( wxWindow::FindFocus() != control->GetInputWindow() ) &&
+ ( win->AcceptsFocus() ) )
{
win->SetFocus();
// 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());
{
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
const wxPoint& pt) const
{
if ( statbar->HasFlag(wxST_SIZEGRIP) &&
- statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
+ statbar->GetParent()->HasFlag(wxRESIZE_BORDER) )
{
- wxSize sizeSbar = statbar->GetSize();
+ wxTopLevelWindow *
+ parentTLW = wxDynamicCast(statbar->GetParent(), wxTopLevelWindow);
+
+ wxCHECK_MSG( parentTLW, FALSE,
+ _T("the status bar should be a child of a TLW") );
- return (sizeSbar.x - pt.x) < (wxCoord)STATUSBAR_GRIP_SIZE &&
- (sizeSbar.y - pt.y) < (wxCoord)STATUSBAR_GRIP_SIZE;
+ // 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;
return wxStdInputHandler::HandleMouseMove(consumer, event);
}
+// ----------------------------------------------------------------------------
+// wxWin32FrameInputHandler
+// ----------------------------------------------------------------------------
+
+class wxWin32SystemMenuEvtHandler : public wxEvtHandler
+{
+public:
+ wxWin32SystemMenuEvtHandler(wxWin32FrameInputHandler *handler);
+
+ void Attach(wxInputConsumer *consumer);
+ void Detach();
+
+private:
+ DECLARE_EVENT_TABLE()
+ void OnSystemMenu(wxCommandEvent &event);
+ void OnCloseFrame(wxCommandEvent &event);
+ void OnClose(wxCloseEvent &event);
+
+ wxWin32FrameInputHandler *m_inputHnd;
+ wxTopLevelWindow *m_wnd;
+ wxAcceleratorTable m_oldAccelTable;
+};
+
+wxWin32SystemMenuEvtHandler::wxWin32SystemMenuEvtHandler(
+ wxWin32FrameInputHandler *handler)
+{
+ m_inputHnd = handler;
+ m_wnd = NULL;
+}
+
+void wxWin32SystemMenuEvtHandler::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 wxWin32SystemMenuEvtHandler::Detach()
+{
+ if ( m_wnd )
+ {
+ m_wnd->SetAcceleratorTable(m_oldAccelTable);
+ m_wnd->RemoveEventHandler(this);
+ m_wnd = NULL;
+ }
+}
+
+BEGIN_EVENT_TABLE(wxWin32SystemMenuEvtHandler, wxEvtHandler)
+ EVT_MENU(wxID_SYSTEM_MENU, wxWin32SystemMenuEvtHandler::OnSystemMenu)
+ EVT_MENU(wxID_CLOSE_FRAME, wxWin32SystemMenuEvtHandler::OnCloseFrame)
+ EVT_CLOSE(wxWin32SystemMenuEvtHandler::OnClose)
+END_EVENT_TABLE()
+
+void wxWin32SystemMenuEvtHandler::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 wxWin32SystemMenuEvtHandler::OnCloseFrame(wxCommandEvent &WXUNUSED(event))
+{
+ m_wnd->PerformAction(wxACTION_TOPLEVEL_BUTTON_CLICK,
+ wxTOPLEVEL_BUTTON_CLOSE);
+}
+
+void wxWin32SystemMenuEvtHandler::OnClose(wxCloseEvent &event)
+{
+ m_wnd = NULL;
+ event.Skip();
+}
+
+
+wxWin32FrameInputHandler::wxWin32FrameInputHandler(wxInputHandler *handler)
+ : wxStdFrameInputHandler(handler)
+{
+ m_menuHandler = new wxWin32SystemMenuEvtHandler(this);
+}
+
+wxWin32FrameInputHandler::~wxWin32FrameInputHandler()
+{
+ if ( m_menuHandler )
+ {
+ m_menuHandler->Detach();
+ delete m_menuHandler;
+ }
+}
+
+bool wxWin32FrameInputHandler::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 wxWin32FrameInputHandler::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 wxWin32FrameInputHandler::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);
+}