From 75f11ad7ca4201f7e2626a2bf5ad84a01296eb4a Mon Sep 17 00:00:00 2001 From: David Webster Date: Mon, 11 Oct 1999 02:49:06 +0000 Subject: [PATCH] *** empty log message *** git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3924 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/os2/accel.h | 14 +- include/wx/os2/dc.h | 4 + include/wx/os2/listctrl.h | 74 +-- include/wx/os2/mdi.h | 143 +++-- include/wx/os2/menu.h | 395 ++++++++----- include/wx/os2/menuitem.h | 15 +- include/wx/os2/metafile.h | 158 +++-- include/wx/os2/minifram.h | 21 +- src/os2/accel.cpp | 44 +- src/os2/listctrl.cpp | 936 ++++++++++++++++++++++++------ src/os2/main.cpp | 8 +- src/os2/makefile.va | 22 +- src/os2/mdi.cpp | 1149 +++++++++++++++++++++++++++++++++---- src/os2/menu.cpp | 1122 +++++++++++++++++++++++++++--------- src/os2/menuitem.cpp | 182 +++++- src/os2/metafile.cpp | 295 ++++++++-- src/os2/minifram.cpp | 22 +- 17 files changed, 3637 insertions(+), 967 deletions(-) diff --git a/include/wx/os2/accel.h b/include/wx/os2/accel.h index ec39737483..49c4126393 100644 --- a/include/wx/os2/accel.h +++ b/include/wx/os2/accel.h @@ -67,11 +67,19 @@ public: ~wxAcceleratorTable(); - inline wxAcceleratorTable& operator = (const wxAcceleratorTable& accel) { if (*this == accel) return (*this); Ref(accel); return *this; } - inline bool operator == (const wxAcceleratorTable& accel) { return m_refData == accel.m_refData; } - inline bool operator != (const wxAcceleratorTable& accel) { return m_refData != accel.m_refData; } + inline wxAcceleratorTable& operator = (const wxAcceleratorTable& accel) + { if (*this == accel) return (*this); Ref(accel); return *this; }; + inline bool operator == (const wxAcceleratorTable& accel) + { return m_refData == accel.m_refData; }; + inline bool operator != (const wxAcceleratorTable& accel) + { return m_refData != accel.m_refData; }; bool Ok() const; + void SetHACCEL(WXHACCEL hAccel); + WXHACCEL GetHACCEL() const; + + // translate the accelerator, return TRUE if done + bool Translate(wxWindow *window, WXMSG *msg) const; }; WXDLLEXPORT_DATA(extern wxAcceleratorTable) wxNullAcceleratorTable; diff --git a/include/wx/os2/dc.h b/include/wx/os2/dc.h index 3f9cbaec2b..d3181b2209 100644 --- a/include/wx/os2/dc.h +++ b/include/wx/os2/dc.h @@ -143,6 +143,10 @@ class WXDLLEXPORT wxDC: public wxDCBase virtual void DoDrawSpline(wxList *points); #endif + // OS2-specific member variables + int m_windowExtX; + int m_windowExtY; + //----------------------------------------------------------------------------- // Other virtuals from wxDCBase that are overridden here //----------------------------------------------------------------------------- diff --git a/include/wx/os2/listctrl.h b/include/wx/os2/listctrl.h index 6dfc25df98..dd764cc1e8 100644 --- a/include/wx/os2/listctrl.h +++ b/include/wx/os2/listctrl.h @@ -1,21 +1,17 @@ ///////////////////////////////////////////////////////////////////////////// // Name: listctrl.h // Purpose: wxListCtrl class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_LISTCTRL_H_ #define _WX_LISTCTRL_H_ -#ifdef __GNUG__ -#pragma interface "listctrl.h" -#endif - #include "wx/control.h" #include "wx/event.h" #include "wx/imaglist.h" @@ -98,7 +94,7 @@ enum { wxLIST_NEXT_ALL, // Searches for subsequent item by index wxLIST_NEXT_BELOW, // Searches for an item below the specified item wxLIST_NEXT_LEFT, // Searches for an item to the left of the specified item - wxLIST_NEXT_RIGHT, // Searches for an item to the right of the specified item + wxLIST_NEXT_RIGHT // Searches for an item to the right of the specified item }; // Alignment flags for Arrange @@ -189,6 +185,10 @@ class WXDLLEXPORT wxListCtrl: public wxControl // Attributes //////////////////////////////////////////////////////////////////////////// + // Sets the background colour (GetBackgroundColour already implicit in + // wxWindow class) + bool SetBackgroundColour(const wxColour& col); + // Gets information about this column bool GetColumn(int col, wxListItem& item) const; @@ -285,11 +285,11 @@ class WXDLLEXPORT wxListCtrl: public wxControl // Returns the item or -1 if unsuccessful. long GetNextItem(long item, int geometry = wxLIST_NEXT_ALL, int state = wxLIST_STATE_DONTCARE) const ; - // Implementation: converts wxWindows style to MSW style. + // Implementation: converts wxWindows style to OS2 style. // Can be a single style flag or a bit list. // oldStyle is 'normalised' so that it doesn't contain // conflicting styles. - long ConvertToMSWStyle(long& oldStyle, long style) const; + long ConvertToOS2Style(long& oldStyle, long style) const; // Gets one of the three image lists wxImageList *GetImageList(int which) const ; @@ -390,15 +390,16 @@ class WXDLLEXPORT wxListCtrl: public wxControl // data is arbitrary data to be passed to the sort function. bool SortItems(wxListCtrlCompare fn, long data); -/* Why should we need this function? Leave for now. - * We might need it because item data may have changed, - * but the display needs refreshing (in string callback mode) - // Updates an item. If the list control has the wxLI_AUTO_ARRANGE style, - // the items will be rearranged. - bool Update(long item); -*/ + // IMPLEMENTATION + virtual bool OS2Command(WXUINT param, WXWORD id); + virtual bool OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result); - void Command(wxCommandEvent& event) { ProcessCommand(event); }; + // bring the control in sync with current m_windowStyle value + void UpdateStyle(); + + // Add to pool: necessary because Windows needs to have a string + // still exist across 3 callbacks. + wxChar *AddPool(const wxString& str); protected: wxTextCtrl* m_textCtrl; // The control used for editing a label @@ -412,40 +413,9 @@ protected: int m_colCount; // Windows doesn't have GetColumnCount so must // keep track of inserted/deleted columns +private: + bool DoCreateControl(int x, int y, int w, int h); }; -class WXDLLEXPORT wxListEvent: public wxCommandEvent -{ - DECLARE_DYNAMIC_CLASS(wxListEvent) - - public: - wxListEvent(wxEventType commandType = wxEVT_NULL, int id = 0); - - int m_code; - long m_itemIndex; - long m_oldItemIndex; - int m_col; - bool m_cancelled; - wxPoint m_pointDrag; - - wxListItem m_item; -}; - -typedef void (wxEvtHandler::*wxListEventFunction)(wxListEvent&); - -#define EVT_LIST_BEGIN_DRAG(id, fn) { wxEVT_COMMAND_LIST_BEGIN_DRAG, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_BEGIN_RDRAG(id, fn) { wxEVT_COMMAND_LIST_BEGIN_RDRAG, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_BEGIN_LABEL_EDIT(id, fn) { wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_END_LABEL_EDIT(id, fn) { wxEVT_COMMAND_LIST_END_LABEL_EDIT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_DELETE_ITEM(id, fn) { wxEVT_COMMAND_LIST_DELETE_ITEM, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_DELETE_ALL_ITEMS(id, fn) { wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_GET_INFO(id, fn) { wxEVT_COMMAND_LIST_GET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_SET_INFO(id, fn) { wxEVT_COMMAND_LIST_SET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_ITEM_SELECTED(id, fn) { wxEVT_COMMAND_LIST_ITEM_SELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_ITEM_DESELECTED(id, fn) { wxEVT_COMMAND_LIST_ITEM_DESELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_KEY_DOWN(id, fn) { wxEVT_COMMAND_LIST_KEY_DOWN, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_INSERT_ITEM(id, fn) { wxEVT_COMMAND_LIST_INSERT_ITEM, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, -#define EVT_LIST_COL_CLICK(id, fn) { wxEVT_COMMAND_LIST_COL_CLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL }, - #endif // _WX_LISTCTRL_H_ diff --git a/include/wx/os2/mdi.h b/include/wx/os2/mdi.h index 841156c16f..83de722b34 100644 --- a/include/wx/os2/mdi.h +++ b/include/wx/os2/mdi.h @@ -3,21 +3,17 @@ // Purpose: MDI (Multiple Document Interface) classes. // This doesn't have to be implemented just like Windows, // it could be a tabbed design as in wxGTK. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_MDI_H_ #define _WX_MDI_H_ -#ifdef __GNUG__ -#pragma interface "mdi.h" -#endif - #include "wx/frame.h" WXDLLEXPORT_DATA(extern const char*) wxFrameNameStr; @@ -55,40 +51,60 @@ public: long style = wxDEFAULT_FRAME_STYLE | wxVSCROLL | wxHSCROLL, const wxString& name = wxFrameNameStr); - void OnSize(wxSizeEvent& event); - void OnActivate(wxActivateEvent& event); - void OnSysColourChanged(wxSysColourChangedEvent& event); + // accessors + // --------- + + // Get the active MDI child window (Windows only) + wxMDIChildFrame *GetActiveChild() const; + + // Get the client window + wxMDIClientWindow *GetClientWindow() const { return m_clientWindow; } + + // Create the client window class (don't Create the window, + // just return a new class) + virtual wxMDIClientWindow *OnCreateClient(void); + + WXHMENU GetWindowMenu() const { return m_windowMenu; } - void SetMenuBar(wxMenuBar *menu_bar); + // MDI operations + // -------------- + virtual void Cascade(); + virtual void Tile(); + virtual void ArrangeIcons(); + virtual void ActivateNext(); + virtual void ActivatePrevious(); - // Gets the size available for subwindows after menu size, toolbar size - // and status bar size have been subtracted. If you want to manage your own - // toolbar(s), don't call SetToolBar. - void GetClientSize(int *width, int *height) const; + // handlers + // -------- - // Get the active MDI child window (Windows only) - wxMDIChildFrame *GetActiveChild() const ; + // Responds to colour changes + void OnSysColourChanged(wxSysColourChangedEvent& event); - // Get the client window - inline wxMDIClientWindow *GetClientWindow() const { return m_clientWindow; }; + void OnSize(wxSizeEvent& event); - // Create the client window class (don't Create the window, - // just return a new class) - virtual wxMDIClientWindow *OnCreateClient() ; + bool HandleActivate(int state, bool minimized, WXHWND activate); + bool HandleCommand(WXWORD id, WXWORD cmd, WXHWND control); - // MDI operations - virtual void Cascade(); - virtual void Tile(); - virtual void ArrangeIcons(); - virtual void ActivateNext(); - virtual void ActivatePrevious(); + // override window proc for MDI-specific message processing + virtual MRESULT OS2WindowProc(HWND hwnd, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); + + virtual MRESULT OS2DefWindowProc(HWND hwnd, WXUINT, WXWPARAM, WXLPARAM); + virtual bool OS2TranslateMessage(WXMSG* msg); protected: + virtual void InternalSetMenuBar(); + + wxMDIClientWindow * m_clientWindow; + wxMDIChildFrame * m_currentChild; + WXHMENU m_windowMenu; - // TODO maybe have this member - wxMDIClientWindow *m_clientWindow; + // TRUE if MDI Frame is intercepting commands, not child + bool m_parentFrameActive; -DECLARE_EVENT_TABLE() +private: + friend class WXDLLEXPORT wxMDIChildFrame; + + DECLARE_EVENT_TABLE() }; class WXDLLEXPORT wxMDIChildFrame: public wxFrame @@ -118,18 +134,31 @@ public: long style = wxDEFAULT_FRAME_STYLE, const wxString& name = wxFrameNameStr); - // Set menu bar - void SetMenuBar(wxMenuBar *menu_bar); - void SetClientSize(int width, int height); - void GetPosition(int *x, int *y) const ; + // MDI operations + virtual void Maximize(bool maximize = TRUE); + virtual void Restore(); + virtual void Activate(); - // MDI operations - virtual void Maximize(); - virtual void Restore(); - virtual void Activate(); -private: - // supress virtual function hiding warning - virtual void Maximize(bool maximize) { wxFrame::Maximize(maximize); }; + // Handlers + + bool HandleMDIActivate(long bActivate, WXHWND, WXHWND); + bool HandleSize(int x, int y, WXUINT); + bool HandleWindowPosChanging(void *lpPos); + bool HandleCommand(WXWORD id, WXWORD cmd, WXHWND control); + + virtual MRESULT OS2WindowProc(HWND hwnd, WXUINT message, WXWPARAM wParam, WXLPARAM lParam); + virtual MRESULT OS2DefWindowProc(HWND hwnd, WXUINT message, WXWPARAM wParam, WXLPARAM lParam); + virtual bool OS2TranslateMessage(WXMSG *msg); + + virtual void OS2DestroyWindow(); + + // Implementation + bool ResetWindowStyle(void *vrect); + +protected: + virtual void DoGetPosition(int *x, int *y) const; + virtual void DoSetClientSize(int width, int height); + virtual void InternalSetMenuBar(); }; /* The client window is a child of the parent MDI frame, and itself @@ -142,25 +171,31 @@ private: class WXDLLEXPORT wxMDIClientWindow: public wxWindow { DECLARE_DYNAMIC_CLASS(wxMDIClientWindow) + public: - wxMDIClientWindow() ; - inline wxMDIClientWindow(wxMDIParentFrame *parent, long style = 0) - { - CreateClient(parent, style); - } + wxMDIClientWindow() { Init(); } + wxMDIClientWindow(wxMDIParentFrame *parent, long style = 0) + { + Init(); - ~wxMDIClientWindow(); + CreateClient(parent, style); + } - // Note: this is virtual, to allow overridden behaviour. - virtual bool CreateClient(wxMDIParentFrame *parent, long style = wxVSCROLL | wxHSCROLL); + // Note: this is virtual, to allow overridden behaviour. + virtual bool CreateClient(wxMDIParentFrame *parent, + long style = wxVSCROLL | wxHSCROLL); - // Explicitly call default scroll behaviour - void OnScroll(wxScrollEvent& event); + // Explicitly call default scroll behaviour + void OnScroll(wxScrollEvent& event); protected: + void Init() { m_scrollX = m_scrollY = 0; } -DECLARE_EVENT_TABLE() + int m_scrollX, m_scrollY; + +private: + DECLARE_EVENT_TABLE() }; #endif diff --git a/include/wx/os2/menu.h b/include/wx/os2/menu.h index db15f8fc70..fd07f0fb9e 100644 --- a/include/wx/os2/menu.h +++ b/include/wx/os2/menu.h @@ -1,27 +1,30 @@ ///////////////////////////////////////////////////////////////////////////// // Name: menu.h // Purpose: wxMenu, wxMenuBar classes -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_MENU_H_ #define _WX_MENU_H_ -#ifdef __GNUG__ -#pragma interface "menu.h" -#endif - #include "wx/defs.h" #include "wx/event.h" +#include "wx/dynarray.h" +#include "wx/string.h" + +#if wxUSE_ACCEL +#include "wx/accel.h" +#endif // wxUSE_ACCEL class WXDLLEXPORT wxMenuItem; class WXDLLEXPORT wxMenuBar; class WXDLLEXPORT wxMenu; +class WXDLLEXPORT wxFrame; WXDLLEXPORT_DATA(extern const char*) wxEmptyString; @@ -33,140 +36,268 @@ class WXDLLEXPORT wxMenu: public wxEvtHandler DECLARE_DYNAMIC_CLASS(wxMenu) public: - // ctor & dtor - wxMenu(const wxString& title = wxEmptyString, const wxFunction func = NULL); - ~wxMenu(); - - // construct menu - // append items to the menu - // separator line - void AppendSeparator(); - // normal item - void Append(int id, const wxString& Label, const wxString& helpString = wxEmptyString, - bool checkable = FALSE); - // a submenu - void Append(int id, const wxString& Label, wxMenu *SubMenu, - const wxString& helpString = wxEmptyString); - // the most generic form (create wxMenuItem first and use it's functions) - void Append(wxMenuItem *pItem); - // insert a break in the menu - void Break(); - // delete an item - void Delete(int id); - - // menu item control - void Enable(int id, bool Flag); - bool Enabled(int id) const; - inline bool IsEnabled(int id) const { return Enabled(id); }; - void Check(int id, bool Flag); - bool Checked(int id) const; - inline bool IsChecked(int id) const { return IsChecked(id); }; - - // Client data - inline void SetClientData(void* clientData) { m_clientData = clientData; } - inline void* GetClientData() const { return m_clientData; } - - void SetInvokingWindow(wxWindow *pWin) { m_pInvokingWindow = pWin; } - wxWindow *GetInvokingWindow() const { return m_pInvokingWindow; } - - // item properties - // title - void SetTitle(const wxString& label); - const wxString GetTitle() const; - // label - void SetLabel(int id, const wxString& label); - wxString GetLabel(int id) const; - // help string - virtual void SetHelpString(int id, const wxString& helpString); - virtual wxString GetHelpString(int id) const ; - - // find item - // Finds the item id matching the given string, -1 if not found. - virtual int FindItem(const wxString& itemString) const ; - // Find wxMenuItem by ID, and item's menu too if itemMenu is !NULL. - wxMenuItem *FindItemForId(int itemId, wxMenu **itemMenu = NULL) const; - - void ProcessCommand(wxCommandEvent& event); - inline void Callback(const wxFunction func) { m_callback = func; } - - // Updates the UI for a menu and all submenus recursively. - // source is the object that has the update event handlers - // defined for it. If NULL, the menu or associated window - // will be used. - void UpdateUI(wxEvtHandler* source = (wxEvtHandler*) NULL); - - virtual void SetParent(wxEvtHandler *parent) { m_parent = parent; } - inline void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; } - inline wxEvtHandler *GetEventHandler() { return m_eventHandler; } - - inline wxList& GetItems() const { return (wxList&) m_menuItems; } + wxMenu(const wxString& title, + const wxFunction func) + { + Init(title, func); + } -public: - wxFunction m_callback; - - int m_noItems; - wxString m_title; - wxMenuBar * m_menuBar; - wxList m_menuItems; - wxEvtHandler * m_parent; - wxEvtHandler * m_eventHandler; - void* m_clientData; - wxWindow* m_pInvokingWindow; + wxMenu( long WXUNUSED(style) ) + { + Init( wxEmptyString ); + } + + wxMenu(const wxString& title = wxEmptyString, long WXUNUSED(style) = 0) + { + Init(title); + } + + virtual ~wxMenu(); + + // construct menu + // append a separator to the menu + void AppendSeparator(); + // append a normal item to the menu + void Append(int id, const wxString& label, + const wxString& helpString = wxEmptyString, + bool checkable = FALSE); + // append a submenu + void Append(int id, const wxString& label, + wxMenu *submenu, + const wxString& helpString = wxEmptyString); + // append anything (create wxMenuItem first) + void Append(wxMenuItem *pItem); + + // insert a break in the menu + void Break(); + + // delete an item + // If it's a submenu, menu is not destroyed. + // VZ: why? shouldn't it return "wxMenu *" then? + void Delete(int id); + + // client data + inline void SetClientData(void* clientData) { m_clientData = clientData; } + inline void* GetClientData() const { return m_clientData; } + + // menu item control + // enable/disable item + void Enable(int id, bool enable); + // TRUE if enabled + bool IsEnabled(int id) const; + + // check/uncheck item - only for checkable items, of course + void Check(int id, bool check); + // TRUE if checked + bool IsChecked(int id) const; + + // other properties + // the menu title + void SetTitle(const wxString& label); + const wxString GetTitle() const; + // the item label + void SetLabel(int id, const wxString& label); + wxString GetLabel(int id) const; + // help string + virtual void SetHelpString(int id, const wxString& helpString); + virtual wxString GetHelpString(int id) const; + + // get the list of items + inline wxList& GetItems() const { return (wxList &)m_menuItems; } + + // find item + // returns id of the item matching the given string or wxNOT_FOUND + virtual int FindItem(const wxString& itemString) const; + // returns NULL if not found + inline wxMenuItem* FindItem(int id) const { return FindItemForId(id); } + // find wxMenuItem by ID, and item's menu too if itemMenu is !NULL + wxMenuItem *FindItemForId(int itemId, wxMenu **itemMenu = NULL) const; + + // Updates the UI for a menu and all submenus recursively. source is the + // object that has the update event handlers defined for it. If NULL, the + // menu or associated window will be used. + void UpdateUI(wxEvtHandler* source = (wxEvtHandler*)NULL); + + bool ProcessCommand(wxCommandEvent& event); + + inline virtual void SetParent(wxEvtHandler *parent) { m_parent = parent; } + inline void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; } + inline wxEvtHandler *GetEventHandler() const { return m_eventHandler; } + + // IMPLEMENTATION + bool OS2Command(WXUINT param, WXWORD id); + + inline void SetInvokingWindow(wxWindow *pWin) { m_pInvokingWindow = pWin; } + inline wxWindow *GetInvokingWindow() const { return m_pInvokingWindow; } + + // semi-private accessors + // get the window which contains this menu + wxWindow *GetWindow() const; + // get the menu handle + WXHMENU GetHMenu() const; + + // only for wxMenuBar + void Attach(wxMenuBar *menubar); + void Detach(); + +#if wxUSE_ACCEL + inline size_t GetAccelCount() const { return m_accelKeyCodes.GetCount(); } + size_t CopyAccels(wxAcceleratorEntry *accels) const; +#endif // wxUSE_ACCEL + + inline wxFunction GetCallback() const { return m_callback; } + inline void Callback(const wxFunction func) { m_callback = func; } + wxFunction m_callback; + +#ifdef WXWIN_COMPATIBILITY + // compatibility: these functions are deprecated + inline bool Enabled(int id) const { return IsEnabled(id); } + inline bool Checked(int id) const { return IsChecked(id); } + +#endif // WXWIN_COMPATIBILITY + +private: + // common part of all ctors + void Init(const wxString& title, const wxFunction func = NULL ); + + bool m_doBreak; + + // This is used when m_hMenu is NULL because we don't want to + // delete it in ~wxMenu (it's been added to a parent menu). + // But we'll still need the handle for other purposes. + // Might be better to have a flag saying whether it's deleteable or not. + WXHMENU m_savehMenu ; // Used for Enable() on popup + WXHMENU m_hMenu; + + int m_noItems; + wxString m_title; + wxMenu * m_topLevelMenu; + wxMenuBar * m_menuBar; + wxList m_menuItems; + wxEvtHandler * m_parent; + wxEvtHandler * m_eventHandler; + wxWindow *m_pInvokingWindow; + void* m_clientData; + +#if wxUSE_ACCEL + // the accelerators data + wxArrayInt m_accelKeyCodes, m_accelFlags, m_accelIds; +#endif // wxUSE_ACCEL }; // ---------------------------------------------------------------------------- // Menu Bar (a la Windows) // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxFrame; + class WXDLLEXPORT wxMenuBar: public wxEvtHandler { DECLARE_DYNAMIC_CLASS(wxMenuBar) - wxMenuBar(); - wxMenuBar(int n, wxMenu *menus[], const wxString titles[]); - ~wxMenuBar(); - - void Append(wxMenu *menu, const wxString& title); - // Must only be used AFTER menu has been attached to frame, - // otherwise use individual menus to enable/disable items - void Enable(int Id, bool Flag); - bool Enabled(int Id) const ; - inline bool IsEnabled(int Id) const { return Enabled(Id); }; - void EnableTop(int pos, bool Flag); - void Check(int id, bool Flag); - bool Checked(int id) const ; - inline bool IsChecked(int Id) const { return Checked(Id); }; - void SetLabel(int id, const wxString& label) ; - wxString GetLabel(int id) const ; - void SetLabelTop(int pos, const wxString& label) ; - wxString GetLabelTop(int pos) const ; - virtual void Delete(wxMenu *menu, int index = 0); /* Menu not destroyed */ - virtual bool OnAppend(wxMenu *menu, const char *title); - virtual bool OnDelete(wxMenu *menu, int index); - - virtual void SetHelpString(int Id, const wxString& helpString); - virtual wxString GetHelpString(int Id) const ; - - virtual int FindMenuItem(const wxString& menuString, const wxString& itemString) const ; - - // Find wxMenuItem for item ID, and return item's - // menu too if itemMenu is non-NULL. - wxMenuItem *FindItemForId(int itemId, wxMenu **menuForItem = NULL) const ; - - inline void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; } - inline wxEvtHandler *GetEventHandler() { return m_eventHandler; } - - inline int GetMenuCount() const { return m_menuCount; } - inline wxMenu* GetMenu(int i) const { return m_menus[i]; } - - public: - wxEvtHandler * m_eventHandler; - int m_menuCount; - wxMenu ** m_menus; - wxString * m_titles; - wxFrame * m_menuBarFrame; -/* TODO: data that represents the actual menubar when created. - */ +public: + // ctors & dtor + // default constructor + wxMenuBar(); + // unused under MSW + wxMenuBar(long style); + // menubar takes ownership of the menus arrays but copies the titles + wxMenuBar(int n, wxMenu *menus[], const wxString titles[]); + virtual ~wxMenuBar(); + + // menubar construction + WXHMENU Create(); + void Append(wxMenu *menu, const wxString& title); + void Insert(int pos, wxMenu * menu, const wxString& title); + void ReplaceMenu(int pos, wxMenu * new_menu, const wxString& title); + int FindMenu(const wxString& title); + void Detach(); + virtual void Delete(wxMenu *menu, int index = 0); /* Menu not destroyed */ + + // state control + // NB: must only be used AFTER menu has been attached to frame, + // otherwise use individual menus to enable/disable items + // enable the item + void Enable(int id, bool enable); + // TRUE if item enabled + bool IsEnabled(int id) const; + // + void EnableTop(int pos, bool enable); + + // works only with checkable items + void Check(int id, bool check); + // TRUE if checked + bool IsChecked(int id) const; + + void SetLabel(int id, const wxString& label) ; + wxString GetLabel(int id) const ; + + virtual void SetHelpString(int id, const wxString& helpString); + virtual wxString GetHelpString(int id) const ; + + void SetLabelTop(int pos, const wxString& label) ; + wxString GetLabelTop(int pos) const ; + + // notifications: return FALSE to prevent the menu from being + // appended/deleted + virtual bool OnAppend(wxMenu *menu, const wxChar *title); + virtual bool OnDelete(wxMenu *menu, int index); + + // item search + // by menu and item names, returns wxNOT_FOUND if not found + virtual int FindMenuItem(const wxString& menuString, + const wxString& itemString) const; + // returns NULL if not found + wxMenuItem* FindItem(int id) const { return FindItemForId(id); } + // returns NULL if not found, fills menuForItem if !NULL + wxMenuItem *FindItemForId(int itemId, wxMenu **menuForItem = NULL) const; + + // submenus access + inline int GetMenuCount() const { return m_menuCount; } + inline wxMenu *GetMenu(int i) const { return m_menus[i]; } + + inline void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; } + inline wxEvtHandler *GetEventHandler() { return m_eventHandler; } + +#ifdef WXWIN_COMPATIBILITY + // compatibility: these functions are deprecated + inline bool Enabled(int id) const { return IsEnabled(id); } + inline bool Checked(int id) const { return IsChecked(id); } +#endif // WXWIN_COMPATIBILITY + + // IMPLEMENTATION + // returns TRUE if we're attached to a frame + inline bool IsAttached() const { return m_menuBarFrame != NULL; } + // get the frame we live in + inline wxFrame *GetFrame() const { return m_menuBarFrame; } + // attach to a frame + void Attach(wxFrame *frame); + +#if wxUSE_ACCEL + // get the accel table for the menus + inline const wxAcceleratorTable& GetAccelTable() const { return m_accelTable; } +#endif // wxUSE_ACCEL + + // get the menu handle + inline WXHMENU GetHMenu() const { return m_hMenu; } + + // if the menubar is modified, the display is not updated automatically, + // call this function to update it (m_menuBarFrame should be !NULL) + void Refresh(); + +protected: + // common part of all ctors + void Init(); + + wxEvtHandler *m_eventHandler; + int m_menuCount; + wxMenu **m_menus; + wxString *m_titles; + wxFrame *m_menuBarFrame; + WXHMENU m_hMenu; + +#if wxUSE_ACCEL + // the accelerator table for all accelerators in all our menus + wxAcceleratorTable m_accelTable; +#endif // wxUSE_ACCEL }; #endif // _WX_MENU_H_ diff --git a/include/wx/os2/menuitem.h b/include/wx/os2/menuitem.h index 9c912967f1..9336cca57f 100644 --- a/include/wx/os2/menuitem.h +++ b/include/wx/os2/menuitem.h @@ -2,7 +2,7 @@ // Name: menuitem.h // Purpose: wxMenuItem class // Author: Vadim Zeitlin -// Modified by: +// Modified by: // Created: 11.11.97 // RCS-ID: $Id$ // Copyright: (c) 1998 Vadim Zeitlin @@ -26,7 +26,7 @@ // headers - only because ownerdrw.h is not always included and I don't want // to write #ifdef's everywhere... #if wxUSE_OWNER_DRAWN -#include "wx/ownerdrw.h" + #include "wx/ownerdrw.h" #endif // ---------------------------------------------------------------------------- @@ -55,15 +55,20 @@ public: // accessors (some more are inherited from wxOwnerDrawn or are below) bool IsSeparator() const { return m_idItem == ID_SEPARATOR; } - bool IsEnabled() const { return m_bEnabled; } - bool IsChecked() const { return m_bChecked; } + bool IsEnabled() const { return m_bEnabled; } + bool IsChecked() const { return m_bChecked; } + bool IsSubMenu() const { return GetSubMenu() != NULL; } int GetId() const { return m_idItem; } const wxString& GetHelp() const { return m_strHelp; } wxMenu *GetSubMenu() const { return m_pSubMenu; } + // the id for a popup menu is really its menu handle (as required by + // ::AppendMenu() API) + int GetRealId() const; + // operations - void SetName(const wxString& strName) { m_strName = strName; } + void SetName(const wxString& strName); void SetHelp(const wxString& strHelp) { m_strHelp = strHelp; } void Enable(bool bDoEnable = TRUE); diff --git a/include/wx/os2/metafile.h b/include/wx/os2/metafile.h index d15134c520..c10cd42933 100644 --- a/include/wx/os2/metafile.h +++ b/include/wx/os2/metafile.h @@ -3,86 +3,126 @@ // Purpose: wxMetaFile, wxMetaFileDC classes. // This probably should be restricted to Windows platforms, // but if there is an equivalent on your platform, great. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_METAFIILE_H_ #define _WX_METAFIILE_H_ -#ifdef __GNUG__ -#pragma interface "metafile.h" -#endif - #include "wx/setup.h" + +#if wxUSE_METAFILE #include "wx/dc.h" +#include "wx/gdiobj.h" + +#if wxUSE_DRAG_AND_DROP +#include "wx/dataobj.h" +#endif /* - * Metafile and metafile device context classes - work in Windows 3.1 only + * Metafile and metafile device context classes * */ -class WXDLLEXPORT wxDC; -class WXDLLEXPORT wxMetaFile: public wxObject +#define wxMetaFile wxMetafile +#define wxMetaFileDC wxMetafileDC + +class WXDLLEXPORT wxMetafile; + +class WXDLLEXPORT wxMetafileRefData: public wxGDIRefData +{ + friend class WXDLLEXPORT wxMetafile; +public: + wxMetafileRefData(void); + ~wxMetafileRefData(void); + +public: + WXHANDLE m_metafile; + int m_windowsMappingMode; +}; + +#define M_METAFILEDATA ((wxMetafileRefData *)m_refData) + +class WXDLLEXPORT wxMetafile: public wxGDIObject { - DECLARE_DYNAMIC_CLASS(wxMetaFile) + DECLARE_DYNAMIC_CLASS(wxMetafile) public: - wxMetaFile(const wxString& file = ""); - ~wxMetaFile(); + // Copy constructor + inline wxMetafile(const wxMetafile& metafile) + { Ref(metafile); } + + wxMetafile(const wxString& file = ""); + ~wxMetafile(void); // After this is called, the metafile cannot be used for anything // since it is now owned by the clipboard. virtual bool SetClipboard(int width = 0, int height = 0); virtual bool Play(wxDC *dc); - // TODO - inline bool Ok() { return FALSE; }; + inline bool Ok(void) const { return (M_METAFILEDATA && (M_METAFILEDATA->m_metafile != 0)); }; -/* TODO: Implementation - inline WXHANDLE GetHMETAFILE() { return m_metaFile; } - inline void SetHMETAFILE(WXHANDLE mf) { m_metaFile = mf; } + // Implementation + inline WXHANDLE GetHMETAFILE(void) { return M_METAFILEDATA->m_metafile; } + void SetHMETAFILE(WXHANDLE mf) ; + inline int GetWindowsMappingMode(void) { return M_METAFILEDATA->m_windowsMappingMode; } + void SetWindowsMappingMode(int mm); + + // Operators + inline wxMetafile& operator = (const wxMetafile& metafile) { if (*this == metafile) return (*this); Ref(metafile); return *this; } + inline bool operator == (const wxMetafile& metafile) { return m_refData == metafile.m_refData; } + inline bool operator != (const wxMetafile& metafile) { return m_refData != metafile.m_refData; } protected: - WXHANDLE m_metaFile; -*/ }; -class WXDLLEXPORT wxMetaFileDC: public wxDC +class WXDLLEXPORT wxMetafileDC: public wxDC { - DECLARE_DYNAMIC_CLASS(wxMetaFileDC) + DECLARE_DYNAMIC_CLASS(wxMetafileDC) public: // Don't supply origin and extent // Supply them to wxMakeMetaFilePlaceable instead. - wxMetaFileDC(const wxString& file = ""); + wxMetafileDC(const wxString& file = ""); // Supply origin and extent (recommended). // Then don't need to supply them to wxMakeMetaFilePlaceable. - wxMetaFileDC(const wxString& file, int xext, int yext, int xorg, int yorg); + wxMetafileDC(const wxString& file, int xext, int yext, int xorg, int yorg); - ~wxMetaFileDC(); + ~wxMetafileDC(void); // Should be called at end of drawing - virtual wxMetaFile *Close(); + virtual wxMetafile *Close(void); virtual void SetMapMode(int mode); - virtual void GetTextExtent(const wxString& string, float *x, float *y, - float *descent = NULL, float *externalLeading = NULL, - wxFont *theFont = NULL, bool use16bit = FALSE); + virtual void GetTextExtent(const wxString& string, long *x, long *y, + long *descent = NULL, long *externalLeading = NULL, + wxFont *theFont = NULL, bool use16bit = FALSE) const; // Implementation - inline wxMetaFile *GetMetaFile() { return m_metaFile; } - inline void SetMetaFile(wxMetaFile *mf) { m_metaFile = mf; } - inline int GetWindowsMappingMode() { return m_windowsMappingMode; } + inline wxMetafile *GetMetaFile(void) const { return m_metaFile; } + inline void SetMetaFile(wxMetafile *mf) { m_metaFile = mf; } + inline int GetWindowsMappingMode(void) const { return m_windowsMappingMode; } inline void SetWindowsMappingMode(int mm) { m_windowsMappingMode = mm; } protected: - int m_windowsMappingMode; - wxMetaFile *m_metaFile; + int m_windowsMappingMode; + wxMetafile* m_metaFile; + +private: + // function hiding warning supression + inline virtual void GetTextExtent( const wxString& string + ,long* width + ,long* height + ,long* descent = NULL + ,long* externalLeading = NULL + ,wxFont* theFont = NULL + ) const + { GetTextExtent( string, width, height, descent, externalLeading, theFont, FALSE);}; }; /* @@ -93,10 +133,56 @@ protected: */ // No origin or extent -bool WXDLLEXPORT wxMakeMetaFilePlaceable(const wxString& filename, float scale = 1.0); +#define wxMakeMetaFilePlaceable wxMakeMetafilePlaceable +bool WXDLLEXPORT wxMakeMetafilePlaceable(const wxString& filename, float scale = 1.0); // Optional origin and extent bool WXDLLEXPORT wxMakeMetaFilePlaceable(const wxString& filename, int x1, int y1, int x2, int y2, float scale = 1.0, bool useOriginAndExtent = TRUE); +// ---------------------------------------------------------------------------- +// wxMetafileDataObject is a specialization of wxDataObject for metafile data +// ---------------------------------------------------------------------------- + +// TODO: implement OLE side of things. At present, it's just for clipboard +// use. + +#if wxUSE_DRAG_AND_DROP +class WXDLLEXPORT wxMetafileDataObject : public wxDataObject +{ +public: + // ctors + wxMetafileDataObject() { m_width = 0; m_height = 0; }; + wxMetafileDataObject(const wxMetafile& metafile, int width = 0, int height = 0): + m_metafile(metafile), m_width(width), m_height(height) { } + + void SetMetafile(const wxMetafile& metafile, int w = 0, int h = 0) + { m_metafile = metafile; m_width = w; m_height = h; } + wxMetafile GetMetafile() const { return m_metafile; } + int GetWidth() const { return m_width; } + int GetHeight() const { return m_height; } + + virtual wxDataFormat GetFormat() const { return wxDF_METAFILE; } + +/* ?? + // implement base class pure virtuals + virtual wxDataFormat GetPreferredFormat() const + { return (wxDataFormat) wxDataObject::Text; } + virtual bool IsSupportedFormat(wxDataFormat format) const + { return format == wxDataObject::Text || format == wxDataObject::Locale; } + virtual size_t GetDataSize() const + { return m_strText.Len() + 1; } // +1 for trailing '\0'of course + virtual void GetDataHere(void *pBuf) const + { memcpy(pBuf, m_strText.c_str(), GetDataSize()); } +*/ + +private: + wxMetafile m_metafile; + int m_width; + int m_height; +}; +#endif + +#endif // wxUSE_METAFILE #endif // _WX_METAFIILE_H_ + diff --git a/include/wx/os2/minifram.h b/include/wx/os2/minifram.h index 8f1644d558..37c24c18d6 100644 --- a/include/wx/os2/minifram.h +++ b/include/wx/os2/minifram.h @@ -3,21 +3,17 @@ // Purpose: wxMiniFrame class. A small frame for e.g. floating toolbars. // If there is no equivalent on your platform, just make it a // normal frame. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_MINIFRAM_H_ #define _WX_MINIFRAM_H_ -#ifdef __GNUG__ -#pragma interface "minifram.h" -#endif - #include "wx/frame.h" class WXDLLEXPORT wxMiniFrame: public wxFrame { @@ -25,22 +21,21 @@ class WXDLLEXPORT wxMiniFrame: public wxFrame { DECLARE_DYNAMIC_CLASS(wxMiniFrame) public: - inline wxMiniFrame() {} + inline wxMiniFrame(void) {} inline wxMiniFrame(wxWindow *parent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = wxDEFAULT_FRAME_STYLE|wxTINY_CAPTION_HORIZ, + long style = wxDEFAULT_FRAME_STYLE, const wxString& name = wxFrameNameStr) { - // Use wxFrame constructor in absence of more specific code. - Create(parent, id, title, pos, size, style, name); + Create(parent, id, title, pos, size, style | wxFRAME_TOOL_WINDOW | wxFRAME_FLOAT_ON_PARENT, name); } - ~wxMiniFrame() {} protected: }; #endif // _WX_MINIFRAM_H_ + diff --git a/src/os2/accel.cpp b/src/os2/accel.cpp index b0b8734d55..438c075e32 100644 --- a/src/os2/accel.cpp +++ b/src/os2/accel.cpp @@ -9,13 +9,19 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "accel.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" +#ifndef WX_PRECOMP +#include #include "wx/setup.h" -#include "wx/accel.h" -#include "wx/string.h" +#include "wx/window.h" +#endif + +#include "wx/os2/accel.h" + +#include "wx/os2/private.h" + #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxAcceleratorTable, wxObject) @@ -28,11 +34,9 @@ public: wxAcceleratorRefData(); ~wxAcceleratorRefData(); -/* TODO: implementation inline HACCEL GetHACCEL() const { return m_hAccel; } protected: HACCEL m_hAccel; -*/ }; #define M_ACCELDATA ((wxAcceleratorRefData *)m_refData) @@ -91,3 +95,29 @@ bool wxAcceleratorTable::Ok() const return FALSE; } +void wxAcceleratorTable::SetHACCEL(WXHACCEL hAccel) +{ + if (!M_ACCELDATA) + m_refData = new wxAcceleratorRefData; + + M_ACCELDATA->m_hAccel = (HACCEL) hAccel; +} + +WXHACCEL wxAcceleratorTable::GetHACCEL() const +{ + if (!M_ACCELDATA) + return 0; + return (WXHACCEL) M_ACCELDATA->m_hAccel; +} + +bool wxAcceleratorTable::Translate(wxWindow *window, WXMSG *wxmsg) const +{ + // TODO: +/* + MSG *msg = (MSG *)wxmsg; + + return Ok() && ::TranslateAccelerator(GetHwndOf(window), GetHaccel(), msg); +*/ + return FALSE; +} + diff --git a/src/os2/listctrl.cpp b/src/os2/listctrl.cpp index d1d8445652..7d8aa47552 100644 --- a/src/os2/listctrl.cpp +++ b/src/os2/listctrl.cpp @@ -1,34 +1,45 @@ ///////////////////////////////////////////////////////////////////////////// // Name: listctrl.cpp // Purpose: wxListCtrl. See also Robert's generic wxListCtrl -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "listctrl.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/wx.h" #endif -#include "wx/stubs/textctrl.h" -#include "wx/stubs/listctrl.h" +#include "wx/listctrl.h" +#include "wx/log.h" + +#include "wx/os2/private.h" + +// TODO: not sure if we will need these +/* +static void wxConvertToOS2ListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& tvItem); +static void wxConvertFromOS2ListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& tvItem, HWND getFullInfo = 0); +*/ #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl) IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject) - #endif wxListCtrl::wxListCtrl() { - m_imageListNormal = NULL; - m_imageListSmall = NULL; - m_imageListState = NULL; - m_baseStyle = 0; + m_imageListNormal = NULL; + m_imageListSmall = NULL; + m_imageListState = NULL; + m_baseStyle = 0; m_colCount = 0; + m_textCtrl = NULL; } bool wxListCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -42,6 +53,11 @@ bool wxListCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, con SetValidator(validator); SetName(name); + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; + m_windowStyle = style; SetParent(parent); @@ -51,81 +67,283 @@ bool wxListCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, con if (parent) parent->AddChild(this); // TODO create list control +// DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | +// LVS_SHAREIMAGELISTS | LVS_SHOWSELALWAYS; +// if ( wxStyleHasBorder(m_windowStyle) ) +// wstyle |= WS_BORDER; +// m_baseStyle = wstyle; +// +// if ( !DoCreateControl(x, y, width, height) ) +// return FALSE; +// +// if (parent) +// parent->AddChild(this); return TRUE; } +bool wxListCtrl::DoCreateControl(int x, int y, int w, int h) +{ + DWORD wstyle = m_baseStyle; + + bool want3D; +// TODO +// WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D); + + // Even with extended styles, need to combine with WS_BORDER + // for them to look right. +// if ( want3D ) +// wstyle |= WS_BORDER; + +// long oldStyle = 0; // Dummy +// wstyle |= ConvertToMSWStyle(oldStyle, m_windowStyle); + + // Create the ListView control. +// m_hWnd = (WXHWND)CreateWindowEx(exStyle, +// WC_LISTVIEW, +// wxT(""), +// wstyle, +// x, y, w, h, +// GetWinHwnd(GetParent()), +// (HMENU)m_windowId, +// wxGetInstance(), +// NULL); + +// if ( !m_hWnd ) +// { +// wxLogError(wxT("Can't create list control window.")); +// +// return FALSE; +// } + + // for comctl32.dll v 4.70+ we want to have this attribute because it's + // prettier (and also because wxGTK does it like this) +#ifdef ListView_SetExtendedListViewStyle +// if ( wstyle & LVS_REPORT ) +// { +// ListView_SetExtendedListViewStyle(GetHwnd(), +// LVS_EX_FULLROWSELECT); +// } +#endif // ListView_SetExtendedListViewStyle + + SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + SetForegroundColour(GetParent()->GetForegroundColour()); + +// SubclassWin(m_hWnd); + + return TRUE; +} + +void wxListCtrl::UpdateStyle() +{ +/* + if ( GetHWND() ) + { + // The new window view style + long dummy; + DWORD dwStyleNew = ConvertToMSWStyle(dummy, m_windowStyle); + dwStyleNew |= m_baseStyle; + + // Get the current window style. + DWORD dwStyleOld = ::GetWindowLong(GetHwnd(), GWL_STYLE); + + // Only set the window style if the view bits have changed. + if ( dwStyleOld != dwStyleNew ) + { + ::SetWindowLong(GetHwnd(), GWL_STYLE, dwStyleNew); + } + } +*/ +} wxListCtrl::~wxListCtrl() { + if (m_textCtrl) + { + m_textCtrl->UnsubclassWin(); + m_textCtrl->SetHWND(0); + delete m_textCtrl; + m_textCtrl = NULL; + } } // Add or remove a single window style void wxListCtrl::SetSingleStyle(long style, bool add) { - long flag = GetWindowStyleFlag(); - - // Get rid of conflicting styles - if ( add ) - { - if ( style & wxLC_MASK_TYPE) - flag = flag & ~wxLC_MASK_TYPE ; - if ( style & wxLC_MASK_ALIGN ) - flag = flag & ~wxLC_MASK_ALIGN ; - if ( style & wxLC_MASK_SORT ) - flag = flag & ~wxLC_MASK_SORT ; - } + long flag = GetWindowStyleFlag(); - if ( flag & style ) - { - if ( !add ) - flag -= style; - } - else - { - if ( add ) - { - flag |= style; - } - } + // Get rid of conflicting styles + if ( add ) + { + if ( style & wxLC_MASK_TYPE) + flag = flag & ~wxLC_MASK_TYPE ; + if ( style & wxLC_MASK_ALIGN ) + flag = flag & ~wxLC_MASK_ALIGN ; + if ( style & wxLC_MASK_SORT ) + flag = flag & ~wxLC_MASK_SORT ; + } + + if ( flag & style ) + { + if ( !add ) + flag -= style; + } + else + { + if ( add ) + { + flag |= style; + } + } - m_windowStyle = flag; + m_windowStyle = flag; - /* TODO RecreateWindow(); */ + UpdateStyle(); } // Set the whole window style void wxListCtrl::SetWindowStyleFlag(long flag) { - m_windowStyle = flag; + m_windowStyle = flag; - /* TODO RecreateWindow(); */ + UpdateStyle(); } +// Can be just a single style, or a bitlist +long wxListCtrl::ConvertToOS2Style(long& oldStyle, long style) const +{ + long wstyle = 0; +/* + if ( style & wxLC_ICON ) + { + if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON ) + oldStyle -= LVS_SMALLICON; + if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT ) + oldStyle -= LVS_REPORT; + if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST ) + oldStyle -= LVS_LIST; + wstyle |= LVS_ICON; + } + + if ( style & wxLC_SMALL_ICON ) + { + if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON ) + oldStyle -= LVS_ICON; + if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT ) + oldStyle -= LVS_REPORT; + if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST ) + oldStyle -= LVS_LIST; + wstyle |= LVS_SMALLICON; + } + + if ( style & wxLC_LIST ) + { + if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON ) + oldStyle -= LVS_ICON; + if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT ) + oldStyle -= LVS_REPORT; + if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON ) + oldStyle -= LVS_SMALLICON; + wstyle |= LVS_LIST; + } + + if ( style & wxLC_REPORT ) + { + if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON ) + oldStyle -= LVS_ICON; + if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST ) + oldStyle -= LVS_LIST; + if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON ) + oldStyle -= LVS_SMALLICON; + + wstyle |= LVS_REPORT; + } + + if ( style & wxLC_ALIGN_LEFT ) + { + if ( oldStyle & LVS_ALIGNTOP ) + oldStyle -= LVS_ALIGNTOP; + wstyle |= LVS_ALIGNLEFT; + } + + if ( style & wxLC_ALIGN_TOP ) + { + if ( oldStyle & LVS_ALIGNLEFT ) + oldStyle -= LVS_ALIGNLEFT; + wstyle |= LVS_ALIGNTOP; + } + + if ( style & wxLC_AUTOARRANGE ) + wstyle |= LVS_AUTOARRANGE; + + // Apparently, no such style (documentation wrong?) + // if ( style & wxLC_BUTTON ) + // wstyle |= LVS_BUTTON; + + if ( style & wxLC_NO_SORT_HEADER ) + wstyle |= LVS_NOSORTHEADER; + + if ( style & wxLC_NO_HEADER ) + wstyle |= LVS_NOCOLUMNHEADER; + + if ( style & wxLC_EDIT_LABELS ) + wstyle |= LVS_EDITLABELS; + + if ( style & wxLC_SINGLE_SEL ) + wstyle |= LVS_SINGLESEL; + + if ( style & wxLC_SORT_ASCENDING ) + { + if ( oldStyle & LVS_SORTDESCENDING ) + oldStyle -= LVS_SORTDESCENDING; + wstyle |= LVS_SORTASCENDING; + } + + if ( style & wxLC_SORT_DESCENDING ) + { + if ( oldStyle & LVS_SORTASCENDING ) + oldStyle -= LVS_SORTASCENDING; + wstyle |= LVS_SORTDESCENDING; + } +*/ + return wstyle; +} + +// Sets the background colour (GetBackgroundColour already implicit in +// wxWindow class) +bool wxListCtrl::SetBackgroundColour(const wxColour& col) +{ + if ( !wxWindow::SetBackgroundColour(col) ) + return FALSE; + +// ListView_SetBkColor(GetHwnd(), PALETTERGB(col.Red(), col.Green(), col.Blue())); + + return TRUE; +} // Gets information about this column bool wxListCtrl::GetColumn(int col, wxListItem& item) const { - // TODO + // TODO return FALSE; } // Sets information about this column bool wxListCtrl::SetColumn(int col, wxListItem& item) { - // TODO + // TODO return FALSE; } // Gets the column width int wxListCtrl::GetColumnWidth(int col) const { - // TODO + // TODO return 0; } // Sets the column width bool wxListCtrl::SetColumnWidth(int col, int width) { - // TODO + // TODO return FALSE; } @@ -135,161 +353,161 @@ bool wxListCtrl::SetColumnWidth(int col, int width) // or small icon view) int wxListCtrl::GetCountPerPage() const { - // TODO + // TODO return 0; } // Gets the edit control for editing labels. wxTextCtrl* wxListCtrl::GetEditControl() const { - return m_textCtrl; + return m_textCtrl; } // Gets information about the item bool wxListCtrl::GetItem(wxListItem& info) const { - // TODO + // TODO return FALSE; } // Sets information about the item bool wxListCtrl::SetItem(wxListItem& info) { - // TODO + // TODO return FALSE; } long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId) { - wxListItem info; - info.m_text = label; - info.m_mask = wxLIST_MASK_TEXT; - info.m_itemId = index; - info.m_col = col; - if ( imageId > -1 ) - { - info.m_image = imageId; - info.m_mask |= wxLIST_MASK_IMAGE; - } - return SetItem(info); + wxListItem info; + info.m_text = label; + info.m_mask = wxLIST_MASK_TEXT; + info.m_itemId = index; + info.m_col = col; + if ( imageId > -1 ) + { + info.m_image = imageId; + info.m_mask |= wxLIST_MASK_IMAGE; + } + return SetItem(info); } // Gets the item state int wxListCtrl::GetItemState(long item, long stateMask) const { - wxListItem info; + wxListItem info; - info.m_mask = wxLIST_MASK_STATE ; - info.m_stateMask = stateMask; - info.m_itemId = item; + info.m_mask = wxLIST_MASK_STATE ; + info.m_stateMask = stateMask; + info.m_itemId = item; - if (!GetItem(info)) - return 0; + if (!GetItem(info)) + return 0; - return info.m_state; + return info.m_state; } // Sets the item state bool wxListCtrl::SetItemState(long item, long state, long stateMask) { - wxListItem info; + wxListItem info; - info.m_mask = wxLIST_MASK_STATE ; - info.m_state = state; - info.m_stateMask = stateMask; - info.m_itemId = item; + info.m_mask = wxLIST_MASK_STATE ; + info.m_state = state; + info.m_stateMask = stateMask; + info.m_itemId = item; - return SetItem(info); + return SetItem(info); } // Sets the item image bool wxListCtrl::SetItemImage(long item, int image, int selImage) { - wxListItem info; + wxListItem info; - info.m_mask = wxLIST_MASK_IMAGE ; - info.m_image = image; - info.m_itemId = item; + info.m_mask = wxLIST_MASK_IMAGE ; + info.m_image = image; + info.m_itemId = item; - return SetItem(info); + return SetItem(info); } // Gets the item text wxString wxListCtrl::GetItemText(long item) const { - wxListItem info; + wxListItem info; - info.m_mask = wxLIST_MASK_TEXT ; - info.m_itemId = item; + info.m_mask = wxLIST_MASK_TEXT ; + info.m_itemId = item; - if (!GetItem(info)) - return wxString(""); - return info.m_text; + if (!GetItem(info)) + return wxString(""); + return info.m_text; } // Sets the item text void wxListCtrl::SetItemText(long item, const wxString& str) { - wxListItem info; + wxListItem info; - info.m_mask = wxLIST_MASK_TEXT ; - info.m_itemId = item; - info.m_text = str; + info.m_mask = wxLIST_MASK_TEXT ; + info.m_itemId = item; + info.m_text = str; - SetItem(info); + SetItem(info); } // Gets the item data long wxListCtrl::GetItemData(long item) const { - wxListItem info; + wxListItem info; - info.m_mask = wxLIST_MASK_DATA ; - info.m_itemId = item; + info.m_mask = wxLIST_MASK_DATA ; + info.m_itemId = item; - if (!GetItem(info)) - return 0; - return info.m_data; + if (!GetItem(info)) + return 0; + return info.m_data; } // Sets the item data bool wxListCtrl::SetItemData(long item, long data) { - wxListItem info; + wxListItem info; - info.m_mask = wxLIST_MASK_DATA ; - info.m_itemId = item; - info.m_data = data; + info.m_mask = wxLIST_MASK_DATA ; + info.m_itemId = item; + info.m_data = data; - return SetItem(info); + return SetItem(info); } // Gets the item rectangle bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const { - // TODO + // TODO return FALSE; } // Gets the item position bool wxListCtrl::GetItemPosition(long item, wxPoint& pos) const { - // TODO + // TODO return FALSE; } // Sets the item position. bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos) { - // TODO + // TODO return FALSE; } // Gets the number of items in the list control int wxListCtrl::GetItemCount() const { - // TODO + // TODO return FALSE; } @@ -298,35 +516,35 @@ int wxListCtrl::GetItemCount() const // view, otherwise the large icon view. int wxListCtrl::GetItemSpacing(bool isSmall) const { - // TODO + // TODO return FALSE; } // Gets the number of selected items in the list control int wxListCtrl::GetSelectedItemCount() const { - // TODO + // TODO return FALSE; } // Gets the text colour of the listview wxColour wxListCtrl::GetTextColour() const { - // TODO + // TODO return wxColour(); } // Sets the text colour of the listview void wxListCtrl::SetTextColour(const wxColour& col) { - // TODO + // TODO } // Gets the index of the topmost visible item when in // list or report view long wxListCtrl::GetTopItem() const { - // TODO + // TODO return 0; } @@ -340,43 +558,43 @@ long wxListCtrl::GetTopItem() const // Returns the item or -1 if unsuccessful. long wxListCtrl::GetNextItem(long item, int geom, int state) const { - // TODO + // TODO return 0; } wxImageList *wxListCtrl::GetImageList(int which) const { - if ( which == wxIMAGE_LIST_NORMAL ) + if ( which == wxIMAGE_LIST_NORMAL ) { - return m_imageListNormal; - } - else if ( which == wxIMAGE_LIST_SMALL ) + return m_imageListNormal; + } + else if ( which == wxIMAGE_LIST_SMALL ) { - return m_imageListSmall; - } - else if ( which == wxIMAGE_LIST_STATE ) + return m_imageListSmall; + } + else if ( which == wxIMAGE_LIST_STATE ) { - return m_imageListState; - } - return NULL; + return m_imageListState; + } + return NULL; } void wxListCtrl::SetImageList(wxImageList *imageList, int which) { - int flags = 0; - if ( which == wxIMAGE_LIST_NORMAL ) + int flags = 0; + if ( which == wxIMAGE_LIST_NORMAL ) { - m_imageListNormal = imageList; - } - else if ( which == wxIMAGE_LIST_SMALL ) + m_imageListNormal = imageList; + } + else if ( which == wxIMAGE_LIST_SMALL ) { - m_imageListSmall = imageList; - } - else if ( which == wxIMAGE_LIST_STATE ) + m_imageListSmall = imageList; + } + else if ( which == wxIMAGE_LIST_STATE ) { - m_imageListState = imageList; - } - // TODO set image list + m_imageListState = imageList; + } + // TODO set image list } // Operations @@ -385,35 +603,35 @@ void wxListCtrl::SetImageList(wxImageList *imageList, int which) // Arranges the items bool wxListCtrl::Arrange(int flag) { - // TODO + // TODO return FALSE; } // Deletes an item bool wxListCtrl::DeleteItem(long item) { - // TODO + // TODO return FALSE; } // Deletes all items bool wxListCtrl::DeleteAllItems() { - // TODO + // TODO return FALSE; } // Deletes all items bool wxListCtrl::DeleteAllColumns() { - // TODO + // TODO return FALSE; } // Deletes a column bool wxListCtrl::DeleteColumn(int col) { - // TODO + // TODO return FALSE; } @@ -488,32 +706,32 @@ long wxListCtrl::InsertItem(wxListItem& info) long wxListCtrl::InsertItem(long index, const wxString& label) { - wxListItem info; - info.m_text = label; - info.m_mask = wxLIST_MASK_TEXT; - info.m_itemId = index; - return InsertItem(info); + wxListItem info; + info.m_text = label; + info.m_mask = wxLIST_MASK_TEXT; + info.m_itemId = index; + return InsertItem(info); } // Inserts an image item long wxListCtrl::InsertItem(long index, int imageIndex) { - wxListItem info; - info.m_image = imageIndex; - info.m_mask = wxLIST_MASK_IMAGE; - info.m_itemId = index; - return InsertItem(info); + wxListItem info; + info.m_image = imageIndex; + info.m_mask = wxLIST_MASK_IMAGE; + info.m_itemId = index; + return InsertItem(info); } // Inserts an image/string item long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex) { - wxListItem info; - info.m_image = imageIndex; - info.m_text = label; - info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT; - info.m_itemId = index; - return InsertItem(info); + wxListItem info; + info.m_image = imageIndex; + info.m_text = label; + info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT; + info.m_itemId = index; + return InsertItem(info); } // For list view mode (only), inserts a column. @@ -526,17 +744,17 @@ long wxListCtrl::InsertColumn(long col, wxListItem& item) long wxListCtrl::InsertColumn(long col, const wxString& heading, int format, int width) { - wxListItem item; - item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT; - item.m_text = heading; - if ( width > -1 ) - { - item.m_mask |= wxLIST_MASK_WIDTH; - item.m_width = width; - } - item.m_format = format; + wxListItem item; + item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT; + item.m_text = heading; + if ( width > -1 ) + { + item.m_mask |= wxLIST_MASK_WIDTH; + item.m_width = width; + } + item.m_format = format; - return InsertColumn(col, item); + return InsertColumn(col, item); } // Scrolls the list control. If in icon, small icon or report view mode, @@ -567,6 +785,235 @@ bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data) return FALSE; } +bool wxListCtrl::OS2Command(WXUINT cmd, WXWORD id) +{ +/* + if (cmd == EN_UPDATE) + { + wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id); + event.SetEventObject( this ); + ProcessCommand(event); + return TRUE; + } + else if (cmd == EN_KILLFOCUS) + { + wxCommandEvent event(wxEVT_KILL_FOCUS, id); + event.SetEventObject( this ); + ProcessCommand(event); + return TRUE; + } + else + return FALSE; +*/ + return FALSE; +} + +bool wxListCtrl::OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) +{ + // TODO +/* + wxListEvent event(wxEVT_NULL, m_windowId); + wxEventType eventType = wxEVT_NULL; + NMHDR *hdr1 = (NMHDR *) lParam; + switch ( hdr1->code ) + { + case LVN_BEGINRDRAG: + eventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG; + // fall through + + case LVN_BEGINDRAG: + if ( eventType == wxEVT_NULL ) + { + eventType = wxEVT_COMMAND_LIST_BEGIN_DRAG; + } + + { + NM_LISTVIEW *hdr = (NM_LISTVIEW *)lParam; + event.m_itemIndex = hdr->iItem; + event.m_pointDrag.x = hdr->ptAction.x; + event.m_pointDrag.y = hdr->ptAction.y; + } + break; + + case LVN_BEGINLABELEDIT: + { + eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT; + LV_DISPINFO *info = (LV_DISPINFO *)lParam; + wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd()); + break; + } + + case LVN_COLUMNCLICK: + { + eventType = wxEVT_COMMAND_LIST_COL_CLICK; + NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam; + event.m_itemIndex = -1; + event.m_col = hdr->iSubItem; + break; + } + + case LVN_DELETEALLITEMS: + // what's the sense of generating a wxWin event for this when + // it's absolutely not portable? +#if 0 + eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS; + event.m_itemIndex = -1; +#endif // 0 + + // return TRUE to suppress all additional LVN_DELETEITEM + // notifications - this makes deleting all items from a list ctrl + // much faster + *result = TRUE; + return TRUE; + + case LVN_DELETEITEM: + { + eventType = wxEVT_COMMAND_LIST_DELETE_ITEM; + NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam; + event.m_itemIndex = hdr->iItem; + break; + } + case LVN_ENDLABELEDIT: + { + eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT; + LV_DISPINFO *info = (LV_DISPINFO *)lParam; + wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd()); + if ( info->item.pszText == NULL || info->item.iItem == -1 ) + event.m_cancelled = TRUE; + break; + } + case LVN_GETDISPINFO: + return FALSE; + + // this provokes stack overflow: indeed, wxConvertFromMSWListItem() + // sends us WM_NOTIFY! As it doesn't do anything for now, just leave + // it out. +#if 0 + { + // TODO: some text buffering here, I think + // TODO: API for getting Windows to retrieve values + // on demand. + eventType = wxEVT_COMMAND_LIST_GET_INFO; + LV_DISPINFO *info = (LV_DISPINFO *)lParam; + wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd()); + break; + } +#endif // 0 + + case LVN_INSERTITEM: + { + eventType = wxEVT_COMMAND_LIST_INSERT_ITEM; + NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam; + event.m_itemIndex = hdr->iItem; + break; + } + case LVN_ITEMCHANGED: + { + // This needs to be sent to wxListCtrl as a rather more + // concrete event. For now, just detect a selection + // or deselection. + NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam; + if ( (hdr->uNewState & LVIS_SELECTED) && !(hdr->uOldState & LVIS_SELECTED) ) + { + eventType = wxEVT_COMMAND_LIST_ITEM_SELECTED; + event.m_itemIndex = hdr->iItem; + } + else if ( !(hdr->uNewState & LVIS_SELECTED) && (hdr->uOldState & LVIS_SELECTED) ) + { + eventType = wxEVT_COMMAND_LIST_ITEM_DESELECTED; + event.m_itemIndex = hdr->iItem; + } + else + return FALSE; + break; + } + + case LVN_KEYDOWN: + { + LV_KEYDOWN *info = (LV_KEYDOWN *)lParam; + WORD wVKey = info->wVKey; + + // get the current selection + long lItem = GetNextItem(-1, + wxLIST_NEXT_ALL, + wxLIST_STATE_SELECTED); + + // or activate the selected item if any + if ( lItem != -1 && (wVKey == VK_RETURN || wVKey == VK_SPACE) ) + { + // TODO this behaviour probably should be optional + eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED; + event.m_itemIndex = lItem; + } + else + { + eventType = wxEVT_COMMAND_LIST_KEY_DOWN; + event.m_code = wxCharCodeMSWToWX(wVKey); + } + break; + } + + case NM_DBLCLK: + // if the user processes it in wxEVT_COMMAND_LEFT_CLICK(), don't do + // anything else + if ( wxControl::MSWOnNotify(idCtrl, lParam, result) ) + { + return TRUE; + } + + // else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event + eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED; + break; + + case LVN_SETDISPINFO: + { + eventType = wxEVT_COMMAND_LIST_SET_INFO; + LV_DISPINFO *info = (LV_DISPINFO *)lParam; + wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd()); + break; + } + + default: + return wxControl::MSWOnNotify(idCtrl, lParam, result); + } + + event.SetEventObject( this ); + event.SetEventType(eventType); + + if ( !GetEventHandler()->ProcessEvent(event) ) + return FALSE; + + if (hdr1->code == LVN_GETDISPINFO) + { + LV_DISPINFO *info = (LV_DISPINFO *)lParam; + if ( info->item.mask & LVIF_TEXT ) + { + if ( !event.m_item.m_text.IsNull() ) + { + info->item.pszText = AddPool(event.m_item.m_text); + info->item.cchTextMax = wxStrlen(info->item.pszText) + 1; + } + } + // wxConvertToMSWListItem(this, event.m_item, info->item); + } + + *result = !event.IsAllowed(); +*/ + return TRUE; +} + +wxChar *wxListCtrl::AddPool(const wxString& str) +{ + // Remove the first element if 3 strings exist + if ( m_stringPool.Number() == 3 ) + { + wxNode *node = m_stringPool.First(); + delete[] (char *)node->Data(); + delete node; + } + wxNode *node = m_stringPool.Add(WXSTRINGCAST str); + return (wxChar *)node->Data(); +} // List item structure wxListItem::wxListItem() { @@ -576,21 +1023,168 @@ wxListItem::wxListItem() m_state = 0; m_stateMask = 0; m_image = 0; - m_data = 0; + m_data = 0; - m_format = wxLIST_FORMAT_CENTRE; - m_width = 0; + m_format = wxLIST_FORMAT_CENTRE; + m_width = 0; } +// TODO see if we need these +/* +static void wxConvertFromOS2ListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem, HWND getFullInfo) +{ + info.m_data = lvItem.lParam; + info.m_mask = 0; + info.m_state = 0; + info.m_stateMask = 0; + info.m_itemId = lvItem.iItem; + + long oldMask = lvItem.mask; + + bool needText = FALSE; + if (getFullInfo != 0) + { + if ( lvItem.mask & LVIF_TEXT ) + needText = FALSE; + else + needText = TRUE; + + if ( needText ) + { + lvItem.pszText = new wxChar[513]; + lvItem.cchTextMax = 512; + } + // lvItem.mask |= TVIF_HANDLE | TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM; + lvItem.mask |= LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; + ::SendMessage(getFullInfo, LVM_GETITEM, 0, (LPARAM)& lvItem); + } + + if ( lvItem.mask & LVIF_STATE ) + { + info.m_mask |= wxLIST_MASK_STATE; + + if ( lvItem.stateMask & LVIS_CUT) + { + info.m_stateMask |= wxLIST_STATE_CUT; + if ( lvItem.state & LVIS_CUT ) + info.m_state |= wxLIST_STATE_CUT; + } + if ( lvItem.stateMask & LVIS_DROPHILITED) + { + info.m_stateMask |= wxLIST_STATE_DROPHILITED; + if ( lvItem.state & LVIS_DROPHILITED ) + info.m_state |= wxLIST_STATE_DROPHILITED; + } + if ( lvItem.stateMask & LVIS_FOCUSED) + { + info.m_stateMask |= wxLIST_STATE_FOCUSED; + if ( lvItem.state & LVIS_FOCUSED ) + info.m_state |= wxLIST_STATE_FOCUSED; + } + if ( lvItem.stateMask & LVIS_SELECTED) + { + info.m_stateMask |= wxLIST_STATE_SELECTED; + if ( lvItem.state & LVIS_SELECTED ) + info.m_state |= wxLIST_STATE_SELECTED; + } + } + + if ( lvItem.mask & LVIF_TEXT ) + { + info.m_mask |= wxLIST_MASK_TEXT; + info.m_text = lvItem.pszText; + } + if ( lvItem.mask & LVIF_IMAGE ) + { + info.m_mask |= wxLIST_MASK_IMAGE; + info.m_image = lvItem.iImage; + } + if ( lvItem.mask & LVIF_PARAM ) + info.m_mask |= wxLIST_MASK_DATA; + if ( lvItem.mask & LVIF_DI_SETITEM ) + info.m_mask |= wxLIST_SET_ITEM; + info.m_col = lvItem.iSubItem; + + if (needText) + { + if (lvItem.pszText) + delete[] lvItem.pszText; + } + lvItem.mask = oldMask; +} + +static void wxConvertToOS2ListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem) +{ + lvItem.iItem = (int) info.m_itemId; + + lvItem.iImage = info.m_image; + lvItem.lParam = info.m_data; + lvItem.stateMask = 0; + lvItem.state = 0; + lvItem.mask = 0; + lvItem.iSubItem = info.m_col; + + if (info.m_mask & wxLIST_MASK_STATE) + { + lvItem.mask |= LVIF_STATE; + if (info.m_stateMask & wxLIST_STATE_CUT) + { + lvItem.stateMask |= LVIS_CUT; + if (info.m_state & wxLIST_STATE_CUT) + lvItem.state |= LVIS_CUT; + } + if (info.m_stateMask & wxLIST_STATE_DROPHILITED) + { + lvItem.stateMask |= LVIS_DROPHILITED; + if (info.m_state & wxLIST_STATE_DROPHILITED) + lvItem.state |= LVIS_DROPHILITED; + } + if (info.m_stateMask & wxLIST_STATE_FOCUSED) + { + lvItem.stateMask |= LVIS_FOCUSED; + if (info.m_state & wxLIST_STATE_FOCUSED) + lvItem.state |= LVIS_FOCUSED; + } + if (info.m_stateMask & wxLIST_STATE_SELECTED) + { + lvItem.stateMask |= LVIS_SELECTED; + if (info.m_state & wxLIST_STATE_SELECTED) + lvItem.state |= LVIS_SELECTED; + } + } + + if (info.m_mask & wxLIST_MASK_TEXT) + { + lvItem.mask |= LVIF_TEXT; + if ( ctrl->GetWindowStyleFlag() & wxLC_USER_TEXT ) + { + lvItem.pszText = LPSTR_TEXTCALLBACK; + } + else + { + lvItem.pszText = WXSTRINGCAST info.m_text; + if ( lvItem.pszText ) + lvItem.cchTextMax = info.m_text.Length(); + else + lvItem.cchTextMax = 0; + } + } + if (info.m_mask & wxLIST_MASK_IMAGE) + lvItem.mask |= LVIF_IMAGE; + if (info.m_mask & wxLIST_MASK_DATA) + lvItem.mask |= LVIF_PARAM; +} +*/ + // List event IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxCommandEvent) -wxListEvent::wxListEvent(wxEventType commandType, int id): - wxCommandEvent(commandType, id) +wxListEvent::wxListEvent(wxEventType commandType, int id) + : wxNotifyEvent(commandType, id) { - m_code = 0; - m_itemIndex = 0; - m_col = 0; - m_cancelled = FALSE; + m_code = 0; + m_itemIndex = 0; + m_col = 0; + m_cancelled = FALSE; } diff --git a/src/os2/main.cpp b/src/os2/main.cpp index 47a9924bae..e6537319a7 100644 --- a/src/os2/main.cpp +++ b/src/os2/main.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// // Name: main.cpp // Purpose: Entry point -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #include "wx/app.h" diff --git a/src/os2/makefile.va b/src/os2/makefile.va index 8dfa5ffbdb..2df25f60e5 100644 --- a/src/os2/makefile.va +++ b/src/os2/makefile.va @@ -326,9 +326,15 @@ OS2OBJS = \ ..\os2\$D\iniconf.obj \ ..\os2\$D\joystick.obj \ ..\os2\$D\listbox.obj \ + ..\os2\$D\listctrl.obj \ + ..\os2\$D\main.obj \ + ..\os2\$D\mdi.obj \ + ..\os2\$D\menu.obj \ + ..\os2\$D\menuitem.obj \ + ..\os2\$D\metafile.obj \ + ..\os2\$D\minifram.obj \ ..\os2\$D\window.obj - OS2LIBOBJS = \ accel.obj \ app.obj \ @@ -367,6 +373,13 @@ OS2LIBOBJS = \ iniconf.obj \ joystick.obj \ listbox.obj \ + listctrl.obj \ + main.obj \ + mdi.obj \ + menu.obj \ + menuitem.obj \ + metafile.obj \ + minifram.obj \ window.obj HTMLOBJS = \ @@ -551,6 +564,13 @@ $(OS2LIBOBJS): copy ..\os2\$D\iniconf.obj copy ..\os2\$D\joystick.obj copy ..\os2\$D\listbox.obj + copy ..\os2\$D\listctrl.obj + copy ..\os2\$D\main.obj + copy ..\os2\$D\mdi.obj + copy ..\os2\$D\menu.obj + copy ..\os2\$D\menuitem.obj + copy ..\os2\$D\metafile.obj + copy ..\os2\$D\minifram.obj copy ..\os2\$D\window.obj # wxWindows library as DLL diff --git a/src/os2/mdi.cpp b/src/os2/mdi.cpp index 4869697cd7..b30e8d41d7 100644 --- a/src/os2/mdi.cpp +++ b/src/os2/mdi.cpp @@ -1,265 +1,1174 @@ ///////////////////////////////////////////////////////////////////////////// // Name: mdi.cpp // Purpose: MDI classes -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "mdi.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/setup.h" + #include "wx/frame.h" + #include "wx/menu.h" + #include "wx/app.h" + #include "wx/utils.h" + #include "wx/dialog.h" + #include "wx/statusbr.h" + #include "wx/settings.h" + #include "wx/intl.h" + #include "wx/log.h" #endif #include "wx/mdi.h" -#include "wx/menu.h" -#include "wx/settings.h" +#include "wx/os2/private.h" + +#include + +// --------------------------------------------------------------------------- +// global variables +// --------------------------------------------------------------------------- + +extern wxWindowList wxModelessWindows; // from dialog.cpp +extern wxMenu *wxCurrentPopupMenu; + +extern wxChar wxMDIFrameClassName[]; +extern wxChar wxMDIChildFrameClassName[]; +extern wxWindow *wxWndHook; // from window.cpp + +extern void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win); + +static HWND invalidHandle = 0; + +// --------------------------------------------------------------------------- +// constants +// --------------------------------------------------------------------------- + +static const int IDM_WINDOWTILE = 4001; +static const int IDM_WINDOWTILEHOR = 4001; +static const int IDM_WINDOWCASCADE = 4002; +static const int IDM_WINDOWICONS = 4003; +static const int IDM_WINDOWNEXT = 4004; +static const int IDM_WINDOWTILEVERT = 4005; + +// This range gives a maximum of 500 MDI children. Should be enough :-) +static const int wxFIRST_MDI_CHILD = 4100; +static const int wxLAST_MDI_CHILD = 4600; -extern wxList wxModelessWindows; +// Status border dimensions +static const int wxTHICK_LINE_BORDER = 3; +static const int wxTHICK_LINE_WIDTH = 1; + +// --------------------------------------------------------------------------- +// private functions +// --------------------------------------------------------------------------- + +// set the MDI menus (by sending the WM_MDISETMENU message) and update the menu +// of the parent of win (which is supposed to be the MDI client window) +static void MDISetMenu(wxWindow *win, HMENU hmenuFrame, HMENU hmenuWindow); + +// insert the window menu (subMenu) into menu just before "Help" submenu or at +// the very end if not found +static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu); + +// is this an id of an MDI child? +inline bool IsMdiCommandId(int id) +{ + return (id >= wxFIRST_MDI_CHILD) && (id <= wxLAST_MDI_CHILD); +} + +static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *activate, WXHWND *hwndAct, WXHWND *hwndDeact); + +// =========================================================================== +// implementation +// =========================================================================== + +// --------------------------------------------------------------------------- +// wxWin macros +// --------------------------------------------------------------------------- #if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame) -IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame) -IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow) + IMPLEMENT_DYNAMIC_CLASS(wxMDIParentFrame, wxFrame) + IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame) + IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow) +#endif // USE_SHARED_LIBRARY BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame) - EVT_SIZE(wxMDIParentFrame::OnSize) - EVT_ACTIVATE(wxMDIParentFrame::OnActivate) - EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged) + EVT_SIZE(wxMDIParentFrame::OnSize) + EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged) END_EVENT_TABLE() BEGIN_EVENT_TABLE(wxMDIClientWindow, wxWindow) - EVT_SCROLL(wxMDIClientWindow::OnScroll) + EVT_SCROLL(wxMDIClientWindow::OnScroll) END_EVENT_TABLE() -#endif - -// Parent frame +// =========================================================================== +// wxMDIParentFrame: the frame which contains the client window which manages +// the children +// =========================================================================== wxMDIParentFrame::wxMDIParentFrame() { + m_clientWindow = NULL; + m_currentChild = NULL; + m_windowMenu = 0; + m_parentFrameActive = TRUE; } bool wxMDIParentFrame::Create(wxWindow *parent, - wxWindowID id, - const wxString& title, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) { - if (!parent) - wxTopLevelWindows.Append(this); + m_defaultIcon = (WXHICON) (wxSTD_MDIPARENTFRAME_ICON ? wxSTD_MDIPARENTFRAME_ICON : wxDEFAULT_MDIPARENTFRAME_ICON); - SetName(name); - m_windowStyle = style; + m_clientWindow = NULL; + m_currentChild = NULL; + m_windowMenu = 0; + m_parentFrameActive = TRUE; - if (parent) parent->AddChild(this); + if (!parent) + wxTopLevelWindows.Append(this); - if ( id > -1 ) - m_windowId = id; - else - m_windowId = (int)NewControlId(); + SetName(name); + m_windowStyle = style; - // TODO: create MDI parent frame + if (parent) parent->AddChild(this); - wxModelessWindows.Append(this); + if ( id > -1 ) + m_windowId = id; + else + m_windowId = (int)NewControlId(); - return TRUE; + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; + +// TODO: m_windowMenu = (WXHMENU) ::LoadMenu(wxGetInstance(), wxT("wxWindowMenu")); +/* + DWORD msflags = WS_OVERLAPPED; + if (style & wxMINIMIZE_BOX) + msflags |= WS_MINIMIZEBOX; + if (style & wxMAXIMIZE_BOX) + msflags |= WS_MAXIMIZEBOX; + if (style & wxTHICK_FRAME) + msflags |= WS_THICKFRAME; + if (style & wxSYSTEM_MENU) + msflags |= WS_SYSMENU; + if ((style & wxMINIMIZE) || (style & wxICONIZE)) + msflags |= WS_MINIMIZE; + if (style & wxMAXIMIZE) + msflags |= WS_MAXIMIZE; + if (style & wxCAPTION) + msflags |= WS_CAPTION; + + if (style & wxCLIP_CHILDREN) + msflags |= WS_CLIPCHILDREN; + + wxWindow::MSWCreate(m_windowId, parent, wxMDIFrameClassName, this, title, x, y, width, height, + msflags); +*/ + wxModelessWindows.Append(this); + + return TRUE; } wxMDIParentFrame::~wxMDIParentFrame() { -} + DestroyChildren(); -// Get size *available for subwindows* i.e. excluding menu bar. -void wxMDIParentFrame::GetClientSize(int *x, int *y) const -{ - // TODO -} +// TODO: ::DestroyMenu((HMENU)m_windowMenu); + m_windowMenu = 0; -void wxMDIParentFrame::SetMenuBar(wxMenuBar *menu_bar) -{ - // TODO - if (!menu_bar) + if ( m_clientWindow ) { - m_frameMenuBar = NULL; - return; - } - - if (menu_bar->m_menuBarFrame) - return; + if ( m_clientWindow->OS2GetOldWndProc() ) + m_clientWindow->UnsubclassWin(); - m_frameMenuBar = menu_bar; + m_clientWindow->SetHWND(0); + delete m_clientWindow; + } } -void wxMDIParentFrame::OnSize(wxSizeEvent& event) +void wxMDIParentFrame::InternalSetMenuBar() { -#if wxUSE_CONSTRAINTS - if (GetAutoLayout()) - Layout(); -#endif - int x = 0; - int y = 0; - int width, height; - GetClientSize(&width, &height); + // TODO: +/* + HMENU subMenu = GetSubMenu((HMENU) m_windowMenu, 0); - if ( GetClientWindow() ) - GetClientWindow()->SetSize(x, y, width, height); + m_parentFrameActive = TRUE; + + InsertWindowMenu(GetClientWindow(), m_hMenu, subMenu); +*/ } -void wxMDIParentFrame::OnActivate(wxActivateEvent& event) +void wxMDIParentFrame::OnSize(wxSizeEvent& event) { - // Do nothing + // TODO: +/* + if ( GetClientWindow() ) + { + int width, height; + GetClientSize(&width, &height); + + GetClientWindow()->SetSize(0, 0, width, height); + } +*/ } // Returns the active MDI child window wxMDIChildFrame *wxMDIParentFrame::GetActiveChild() const { - // TODO - return NULL; + HWND hWnd = 0; // TODO: (HWND)::SendMessage(GetWinHwnd(GetClientWindow()), +// WM_MDIGETACTIVE, 0, 0L); + if ( hWnd == 0 ) + return NULL; + else + return (wxMDIChildFrame *)wxFindWinFromHandle((WXHWND) hWnd); } -// Create the client window class (don't Create the window, -// just return a new class) +// Create the client window class (don't Create the window, just return a new +// class) wxMDIClientWindow *wxMDIParentFrame::OnCreateClient() { - return new wxMDIClientWindow ; + return new wxMDIClientWindow; } // Responds to colour changes, and passes event on to children. void wxMDIParentFrame::OnSysColourChanged(wxSysColourChangedEvent& event) { - // TODO + if ( m_clientWindow ) + { + m_clientWindow->SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE)); + m_clientWindow->Refresh(); + } - // Propagate the event to the non-top-level children - wxFrame::OnSysColourChanged(event); + event.Skip(); } +// --------------------------------------------------------------------------- // MDI operations +// --------------------------------------------------------------------------- + void wxMDIParentFrame::Cascade() { - // TODO +// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDICASCADE, 0, 0); } +// TODO: add a direction argument (hor/vert) void wxMDIParentFrame::Tile() { - // TODO +// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDITILE, MDITILE_HORIZONTAL, 0); } void wxMDIParentFrame::ArrangeIcons() { - // TODO +// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDIICONARRANGE, 0, 0); } void wxMDIParentFrame::ActivateNext() { - // TODO +// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDINEXT, 0, 0); } void wxMDIParentFrame::ActivatePrevious() { - // TODO +// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), WM_MDINEXT, 0, 1); } -// Child frame +// --------------------------------------------------------------------------- +// the MDI parent frame window proc +// --------------------------------------------------------------------------- -wxMDIChildFrame::wxMDIChildFrame() +MRESULT wxMDIParentFrame::OS2WindowProc(HWND hwnd, + WXUINT message, + WXWPARAM wParam, + WXLPARAM lParam) { + MRESULT rc = 0; + bool processed = FALSE; + + // TODO: +/* + switch ( message ) + { + case WM_ACTIVATE: + { + WXWORD state, minimized; + WXHWND hwnd; + UnpackActivate(wParam, lParam, &state, &minimized, &hwnd); + + processed = HandleActivate(state, minimized != 0, hwnd); + } + break; + + case WM_COMMAND: + { + WXWORD id, cmd; + WXHWND hwnd; + UnpackCommand(wParam, lParam, &id, &hwnd, &cmd); + + (void)HandleCommand(id, cmd, hwnd); + + // even if the frame didn't process it, there is no need to try it + // once again (i.e. call wxFrame::HandleCommand()) - we just dud it, + // so pretend we processed the message anyhow + processed = TRUE; + } + + // always pass this message DefFrameProc(), otherwise MDI menu + // commands (and sys commands - more surprizingly!) won't work + MSWDefWindowProc(message, wParam, lParam); + break; + + case WM_CREATE: + m_clientWindow = OnCreateClient(); + // Uses own style for client style + if ( !m_clientWindow->CreateClient(this, GetWindowStyleFlag()) ) + { + wxLogMessage(_("Failed to create MDI parent frame.")); + + rc = -1; + } + + processed = TRUE; + break; + + case WM_ERASEBKGND: + processed = TRUE; + + // we erase background ourselves + rc = TRUE; + break; + + case WM_MENUSELECT: + { + WXWORD item, flags; + WXHMENU hmenu; + UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu); + + if ( m_parentFrameActive ) + { + processed = HandleMenuSelect(item, flags, hmenu); + } + else if (m_currentChild) + { + processed = m_currentChild-> + HandleMenuSelect(item, flags, hmenu); + } + } + break; + + case WM_SIZE: + // as we don't (usually) resize the MDI client to exactly fit the + // client area (we put it below the toolbar, above statusbar &c), + // we should not pass this one to DefFrameProc + break; + } +*/ + if ( !processed ) + rc = wxFrame::OS2WindowProc(hwnd, message, wParam, lParam); + + return rc; } -bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, - wxWindowID id, - const wxString& title, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) +bool wxMDIParentFrame::HandleActivate(int state, bool minimized, WXHWND activate) { - SetName(name); + bool processed = FALSE; - if ( id > -1 ) - m_windowId = id; + // TODO: +/* + if ( wxWindow::HandleActivate(state, minimized, activate) ) + { + // already processed + processed = TRUE; + } + + // If this window is an MDI parent, we must also send an OnActivate message + // to the current child. + if ( (m_currentChild != NULL) && + ((state == WA_ACTIVE) || (state == WA_CLICKACTIVE)) ) + { + wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_currentChild->GetId()); + event.SetEventObject( m_currentChild ); + if ( m_currentChild->GetEventHandler()->ProcessEvent(event) ) + processed = TRUE; + } +*/ + return processed; +} + +bool wxMDIParentFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd) +{ + // In case it's e.g. a toolbar. + if ( hwnd ) + { + wxWindow *win = wxFindWinFromHandle(hwnd); + if ( win ) + return FALSE; // Need to get wxWindow for OS/2 up to date: win->OS2Command(cmd, id); + } + + // is it one of standard MDI commands? + WXWPARAM wParam = 0; + int msg; + + // TODO: +/* + switch ( id ) + { + case IDM_WINDOWCASCADE: + msg = WM_MDICASCADE; + wParam = MDITILE_SKIPDISABLED; + break; + + case IDM_WINDOWTILEHOR: + wParam |= MDITILE_HORIZONTAL; + // fall through + + case IDM_WINDOWTILEVERT: + if ( !wParam ) + wParam = MDITILE_VERTICAL; + msg = WM_MDITILE; + wParam |= MDITILE_SKIPDISABLED; + break; + + case IDM_WINDOWICONS: + msg = WM_MDIICONARRANGE; + break; + + case IDM_WINDOWNEXT: + msg = WM_MDINEXT; + break; + + default: + msg = 0; + } +*/ + if ( msg ) + { +// TODO: ::SendMessage(GetWinHwnd(GetClientWindow()), msg, wParam, 0); + + return TRUE; + } + + // FIXME VZ: what does this test do?? + if (id >= 0xF000) + { + return FALSE; // Get WndProc to call default proc + } + + if ( IsMdiCommandId(id) ) + { + wxWindowList::Node* node = GetChildren().GetFirst(); + while ( node ) + { + wxWindow* child = node->GetData(); + if ( child->GetHWND() ) + { + long childId = wxGetWindowId(child->GetHWND()); + if (childId == (long)id) + { +// TODO: ::SendMessage( GetWinHwnd(GetClientWindow()), +// WM_MDIACTIVATE, +// (WPARAM)child->GetHWND(), 0); + return TRUE; + } + } + node = node->GetNext(); + } + } + else if ( m_parentFrameActive ) + { + return ProcessCommand(id); + } + else if ( m_currentChild ) + { + return m_currentChild->HandleCommand(id, cmd, hwnd); + } + else + { + // this shouldn't happen because it means that our messages are being + // lost (they're not sent to the parent frame nor to the children) + wxFAIL_MSG(wxT("MDI parent frame is not active, " + "yet there is no active MDI child?")); + } + + return FALSE; +} + +MRESULT wxMDIParentFrame::OS2DefWindowProc(HWND hwnd, + WXUINT message, + WXWPARAM wParam, + WXLPARAM lParam) +{ + WXHWND clientWnd; + if ( GetClientWindow() ) + clientWnd = GetClientWindow()->GetHWND(); else - m_windowId = (int)NewControlId(); + clientWnd = 0; + +// TODO: return DefFrameProc(GetHwnd(), (HWND)clientWnd, message, wParam, lParam); + return((MRESULT)0); +} - if (parent) parent->AddChild(this); +bool wxMDIParentFrame::OS2TranslateMessage(WXMSG* msg) +{ + // TODO: +/* + if ( m_currentChild && m_currentChild->GetHWND() && + m_currentChild->OS2TranslateMessage(msg) ) + { + return TRUE; + } - // TODO: create child frame + if ( m_acceleratorTable.Translate(this, msg) ) + { + return TRUE; + } - wxModelessWindows.Append(this); + if ( pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN ) + { + if ( ::TranslateMDISysAccel(GetWinHwnd(GetClientWindow()), pMsg)) + return TRUE; + } +*/ return FALSE; } +// =========================================================================== +// wxMDIChildFrame +// =========================================================================== + +wxMDIChildFrame::wxMDIChildFrame() +{ +} + +bool wxMDIChildFrame::Create(wxMDIParentFrame *parent, + wxWindowID id, + const wxString& title, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) +{ + m_defaultIcon = (WXHICON)(wxSTD_MDICHILDFRAME_ICON ? wxSTD_MDICHILDFRAME_ICON + : wxDEFAULT_MDICHILDFRAME_ICON); + + SetName(name); + + if ( id > -1 ) + m_windowId = id; + else + m_windowId = (int)NewControlId(); + + if ( parent ) + { + parent->AddChild(this); + } + + wxWndHook = this; + + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; + + // TODO: +/* + MDICREATESTRUCT mcs; + + mcs.szClass = wxMDIChildFrameClassName; + mcs.szTitle = title; + mcs.hOwner = wxGetInstance(); + if (x > -1) + mcs.x = x; + else + mcs.x = CW_USEDEFAULT; + + if (y > -1) + mcs.y = y; + else + mcs.y = CW_USEDEFAULT; + + if (width > -1) + mcs.cx = width; + else + mcs.cx = CW_USEDEFAULT; + + if (height > -1) + mcs.cy = height; + else + mcs.cy = CW_USEDEFAULT; + + DWORD msflags = WS_OVERLAPPED | WS_CLIPCHILDREN; + if (style & wxMINIMIZE_BOX) + msflags |= WS_MINIMIZEBOX; + if (style & wxMAXIMIZE_BOX) + msflags |= WS_MAXIMIZEBOX; + if (style & wxTHICK_FRAME) + msflags |= WS_THICKFRAME; + if (style & wxSYSTEM_MENU) + msflags |= WS_SYSMENU; + if ((style & wxMINIMIZE) || (style & wxICONIZE)) + msflags |= WS_MINIMIZE; + if (style & wxMAXIMIZE) + msflags |= WS_MAXIMIZE; + if (style & wxCAPTION) + msflags |= WS_CAPTION; + + mcs.style = msflags; + + mcs.lParam = 0; +*/ + DWORD Return = 0; // SendMessage(GetWinHwnd(parent->GetClientWindow()), +// WM_MDICREATE, 0, (LONG)(LPSTR)&mcs); + m_hWnd = (WXHWND)Return; + + wxWndHook = NULL; + wxAssociateWinWithHandle((HWND) GetHWND(), this); + + // VZ: what's this? an act of piracy? + //SetWindowLong(GetHwnd(), 0, (long)this); + + wxModelessWindows.Append(this); + return TRUE; +} + wxMDIChildFrame::~wxMDIChildFrame() { + OS2DestroyWindow(); } // Set the client size (i.e. leave the calculation of borders etc. // to wxWindows) -void wxMDIChildFrame::SetClientSize(int width, int height) +void wxMDIChildFrame::DoSetClientSize(int width, int height) { - // TODO + HWND hWnd = GetHwnd(); + + // TODO: +/* + RECT rect; + ::GetClientRect(hWnd, &rect); + + RECT rect2; + GetWindowRect(hWnd, &rect2); + + // Find the difference between the entire window (title bar and all) + // and the client area; add this to the new client size to move the + // window + int actual_width = rect2.right - rect2.left - rect.right + width; + int actual_height = rect2.bottom - rect2.top - rect.bottom + height; + + if (GetStatusBar()) + { + int sx, sy; + GetStatusBar()->GetSize(&sx, &sy); + actual_height += sy; + } + + POINT point; + point.x = rect2.left; + point.y = rect2.top; + + // If there's an MDI parent, must subtract the parent's top left corner + // since MoveWindow moves relative to the parent + wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent(); + ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point); + + MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE); + + wxSizeEvent event(wxSize(width, height), m_windowId); + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent(event); +*/ } -void wxMDIChildFrame::GetPosition(int *x, int *y) const +void wxMDIChildFrame::DoGetPosition(int *x, int *y) const { - // TODO + // TODO: +/* + RECT rect; + GetWindowRect(GetHwnd(), &rect); + POINT point; + point.x = rect.left; + point.y = rect.top; + + // Since we now have the absolute screen coords, + // if there's a parent we must subtract its top left corner + wxMDIParentFrame *mdiParent = (wxMDIParentFrame *)GetParent(); + ::ScreenToClient((HWND) mdiParent->GetClientWindow()->GetHWND(), &point); + + *x = point.x; + *y = point.y; +*/ } -void wxMDIChildFrame::SetMenuBar(wxMenuBar *menu_bar) +void wxMDIChildFrame::InternalSetMenuBar() { - // TODO - if (!menu_bar) - { - m_frameMenuBar = NULL; - return; - } - - if (menu_bar->m_menuBarFrame) - return; - m_frameMenuBar = menu_bar; + // TODO: +/* + + wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent(); + + HMENU subMenu = GetSubMenu((HMENU)parent->GetWindowMenu(), 0); + + InsertWindowMenu(parent->GetClientWindow(), m_hMenu, subMenu); + + parent->m_parentFrameActive = FALSE; +*/ } +// --------------------------------------------------------------------------- // MDI operations -void wxMDIChildFrame::Maximize() +// --------------------------------------------------------------------------- + +void wxMDIChildFrame::Maximize(bool maximize) { - // TODO + wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent(); + // TODO: +/* + if ( parent && parent->GetClientWindow() ) + { + ::SendMessage(GetWinHwnd(parent->GetClientWindow()), + maximize ? WM_MDIMAXIMIZE : WM_MDIRESTORE, + (WPARAM)GetHwnd(), 0); + } +*/ } void wxMDIChildFrame::Restore() { - // TODO + // TODO: +/* + wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent(); + if ( parent && parent->GetClientWindow() ) + { + ::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIRESTORE, + (WPARAM) GetHwnd(), 0); + } +*/ } void wxMDIChildFrame::Activate() +{ + // TODO: +/* + wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent(); + if ( parent && parent->GetClientWindow() ) + { + ::SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIACTIVATE, + (WPARAM) GetHwnd(), 0); + } +*/ +} + +// --------------------------------------------------------------------------- +// MDI window proc and message handlers +// --------------------------------------------------------------------------- + +MRESULT wxMDIChildFrame::OS2WindowProc(HWND hwnd, + WXUINT message, + WXWPARAM wParam, + WXLPARAM lParam) +{ + MRESULT rc = 0; + bool processed = FALSE; + + // TODO: +/* + switch ( message ) + { + case WM_COMMAND: + { + WORD id, cmd; + WXHWND hwnd; + UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam, + &id, &hwnd, &cmd); + + processed = HandleCommand(id, cmd, (WXHWND)hwnd); + } + break; + + case WM_GETMINMAXINFO: + // let the default window proc calculate the size of MDI children + // frames because it is based on the size of the MDI client window, + // not on the values specified in wxWindow m_min/max variables + return MSWDefWindowProc(message, wParam, lParam); + + case WM_MDIACTIVATE: + { + WXWORD act; + WXHWND hwndAct, hwndDeact; + UnpackMDIActivate(wParam, lParam, &act, &hwndAct, &hwndDeact); + + processed = HandleMDIActivate(act, hwndAct, hwndDeact); + } + // fall through + + case WM_MOVE: + // must pass WM_MOVE to DefMDIChildProc() to recalculate MDI client + // scrollbars if necessary + + // fall through + + case WM_SIZE: + // must pass WM_SIZE to DefMDIChildProc(), otherwise many weird + // things happen + MSWDefWindowProc(message, wParam, lParam); + break; + + case WM_SYSCOMMAND: + // DefMDIChildProc handles SC_{NEXT/PREV}WINDOW here, so pass it + // the message (the base class version does not) + return MSWDefWindowProc(message, wParam, lParam); + + case WM_WINDOWPOSCHANGING: + processed = HandleWindowPosChanging((LPWINDOWPOS)lParam); + break; + } +*/ + if ( !processed ) + rc = wxFrame::OS2WindowProc(hwnd, message, wParam, lParam); + + return rc; +} + +bool wxMDIChildFrame::HandleSize(int x, int y, WXUINT id) +{ + HWND hwnd = GetHwnd(); + + if ( !hwnd || hwnd == invalidHandle ) + { + return FALSE; + } + + // TODO: +/* + switch (id) + { + case SIZEFULLSCREEN: + case SIZENORMAL: + m_iconized = FALSE; + break; + + case SIZEICONIC: + m_iconized = TRUE; + break; + } + + if ( !m_iconized ) + { + // forward WM_SIZE to status bar control +#if wxUSE_NATIVE_STATUSBAR + if (m_frameStatusBar && m_frameStatusBar->IsKindOf(CLASSINFO(wxStatusBar95))) + { + wxSizeEvent event(wxSize(x, y), m_frameStatusBar->GetId()); + event.SetEventObject( m_frameStatusBar ); + + ((wxStatusBar95 *)m_frameStatusBar)->OnSize(event); + } +#endif // wxUSE_NATIVE_STATUSBAR + + PositionStatusBar(); + PositionToolBar(); + + return wxWindow::HandleSize(x, y, id); + } + else + { + return FALSE; + } +*/ + return TRUE; +} + +bool wxMDIChildFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND hwnd) +{ + // In case it's e.g. a toolbar. + if ( hwnd ) + { + wxWindow *win = wxFindWinFromHandle(hwnd); +// if (win) +// Fix dependent stuff return win->OS2Command(cmd, id); + } + + if (wxCurrentPopupMenu) + { + wxMenu *popupMenu = wxCurrentPopupMenu; + wxCurrentPopupMenu = NULL; +// Fix dependent stuff if (popupMenu->OS2Command(cmd, id)) +// return TRUE; + } + + if (GetMenuBar() && GetMenuBar()->FindItemForId(id)) + { + ProcessCommand(id); + return TRUE; + } + else + return FALSE; + + return TRUE; +} + +bool wxMDIChildFrame::HandleMDIActivate(long WXUNUSED(activate), + WXHWND hwndAct, + WXHWND hwndDeact) +{ + wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent(); + + HMENU menuToSet = 0; + + bool activated; + + if ( m_hWnd == hwndAct ) + { + activated = TRUE; + parent->m_currentChild = this; + + HMENU child_menu = (HMENU)GetWinMenu(); + if ( child_menu ) + { + parent->m_parentFrameActive = FALSE; + + menuToSet = child_menu; + } + } + else if ( m_hWnd == hwndDeact ) + { + wxASSERT_MSG( parent->m_currentChild == this, + wxT("can't deactivate MDI child which wasn't active!") ); + + activated = FALSE; + parent->m_currentChild = NULL; + + HMENU parent_menu = (HMENU)parent->GetWinMenu(); + if ( parent_menu ) + { + parent->m_parentFrameActive = TRUE; + + menuToSet = parent_menu; + } + } + else + { + // we have nothing to with it + return FALSE; + } + + if ( menuToSet ) + { + HMENU subMenu = 0; // TODO: GetSubMenu((HMENU) parent->GetWindowMenu(), 0); + + MDISetMenu(parent->GetClientWindow(), menuToSet, subMenu); + } + + wxActivateEvent event(wxEVT_ACTIVATE, activated, m_windowId); + event.SetEventObject( this ); + + return GetEventHandler()->ProcessEvent(event); +} + +bool wxMDIChildFrame::HandleWindowPosChanging(void *pos) +{ +// WINDOWPOS *lpPos = (WINDOWPOS *)pos; + return FALSE; +} + +// --------------------------------------------------------------------------- +// MDI specific message translation/preprocessing +// --------------------------------------------------------------------------- + +MRESULT wxMDIChildFrame::OS2DefWindowProc(HWND hwnd, WXUINT message, WXWPARAM wParam, WXLPARAM lParam) { // TODO +/* + return DefMDIChildProc(GetHwnd(), + (UINT)message, (WPARAM)wParam, (LPARAM)lParam); +*/ + return (MRESULT)0; } -// Client window +bool wxMDIChildFrame::OS2TranslateMessage(WXMSG* msg) +{ + return m_acceleratorTable.Translate(GetParent(), msg); +} -wxMDIClientWindow::wxMDIClientWindow() +// --------------------------------------------------------------------------- +// misc +// --------------------------------------------------------------------------- + +void wxMDIChildFrame::OS2DestroyWindow() { +// get wxWindow up to date OS2DetachWindowMenu(); + invalidHandle = GetHwnd(); + + wxMDIParentFrame *parent = (wxMDIParentFrame *)GetParent(); + + // Must make sure this handle is invalidated (set to NULL) since all sorts + // of things could happen after the child client is destroyed, but before + // the wxFrame is destroyed. + + HWND oldHandle = (HWND)GetHWND(); +// TODO: SendMessage(GetWinHwnd(parent->GetClientWindow()), WM_MDIDESTROY, +// (WPARAM)oldHandle, 0); + invalidHandle = 0; + + if (m_hMenu) + { +// TODO: ::DestroyMenu((HMENU) m_hMenu); + m_hMenu = 0; + } + m_hWnd = 0; } -wxMDIClientWindow::~wxMDIClientWindow() +// Change the client window's extended style so we don't get a client edge +// style when a child is maximised (a double border looks silly.) +bool wxMDIChildFrame::ResetWindowStyle(void *vrect) { + return FALSE; } +// =========================================================================== +// wxMDIClientWindow: the window of predefined (by Windows) class which +// contains the child frames +// =========================================================================== + bool wxMDIClientWindow::CreateClient(wxMDIParentFrame *parent, long style) { - // TODO create client window m_backgroundColour = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE); - return FALSE; + // TODO: +/* + CLIENTCREATESTRUCT ccs; + m_windowStyle = style; + m_parent = parent; + + ccs.hWindowMenu = (HMENU)parent->GetWindowMenu(); + ccs.idFirstChild = wxFIRST_MDI_CHILD; + + DWORD msStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN; + if ( style & wxHSCROLL ) + msStyle |= WS_HSCROLL; + if ( style & wxVSCROLL ) + msStyle |= WS_VSCROLL; + +#if defined(__WIN95__) + DWORD exStyle = WS_EX_CLIENTEDGE; +#else + DWORD exStyle = 0; +#endif + + wxWndHook = this; + m_hWnd = (WXHWND)::CreateWindowEx + ( + exStyle, + wxT("MDICLIENT"), + NULL, + msStyle, + 0, 0, 0, 0, + GetWinHwnd(parent), + NULL, + wxGetInstance(), + (LPSTR)(LPCLIENTCREATESTRUCT)&ccs); + if ( !m_hWnd ) + { + wxLogLastError("CreateWindowEx(MDI client)"); + + return FALSE; + } + + SubclassWin(m_hWnd); + wxWndHook = NULL; +*/ + return TRUE; } // Explicitly call default scroll behaviour void wxMDIClientWindow::OnScroll(wxScrollEvent& event) { - Default(); // Default processing + // Note: for client windows, the scroll position is not set in + // WM_HSCROLL, WM_VSCROLL, so we can't easily determine what + // scroll position we're at. + // This makes it hard to paint patterns or bitmaps in the background, + // and have the client area scrollable as well. + + if ( event.GetOrientation() == wxHORIZONTAL ) + m_scrollX = event.GetPosition(); // Always returns zero! + else + m_scrollY = event.GetPosition(); // Always returns zero! + + event.Skip(); +} + +// --------------------------------------------------------------------------- +// non member functions +// --------------------------------------------------------------------------- + +static void MDISetMenu(wxWindow *win, HMENU hmenuFrame, HMENU hmenuWindow) +{ + // TODO: +/* + ::SendMessage(GetWinHwnd(win), WM_MDISETMENU, + (WPARAM)hmenuFrame, (LPARAM)hmenuWindow); + // update menu bar of the parent window + wxWindow *parent = win->GetParent(); + wxCHECK_RET( parent, wxT("MDI client without parent frame? weird...") ); + + ::DrawMenuBar(GetWinHwnd(parent)); +*/ +} + +static void InsertWindowMenu(wxWindow *win, WXHMENU menu, HMENU subMenu) +{ +/* + // Try to insert Window menu in front of Help, otherwise append it. + HMENU hmenu = (HMENU)menu; + int N = GetMenuItemCount(hmenu); + bool success = FALSE; + for ( int i = 0; i < N; i++ ) + { + wxChar buf[256]; + int chars = GetMenuString(hmenu, i, buf, WXSIZEOF(buf), MF_BYPOSITION); + if ( chars == 0 ) + { + wxLogLastError(wxT("GetMenuString")); + + continue; + } + + if ( wxStripMenuCodes(wxString(buf)).IsSameAs(wxT("Help")) ) + { + success = TRUE; + ::InsertMenu(hmenu, i, MF_BYPOSITION | MF_POPUP | MF_STRING, + (UINT)subMenu, wxT("&Window")); + break; + } + } + + if ( !success ) + { + ::AppendMenu(hmenu, MF_POPUP, (UINT)subMenu, wxT("&Window")); + } + MDISetMenu(win, hmenu, subMenu); +*/ +} + +static void UnpackMDIActivate(WXWPARAM wParam, WXLPARAM lParam, + WXWORD *activate, WXHWND *hwndAct, WXHWND *hwndDeact) +{ + *activate = TRUE; + *hwndAct = (WXHWND)lParam; + *hwndDeact = (WXHWND)wParam; } diff --git a/src/os2/menu.cpp b/src/os2/menu.cpp index 5880beab53..d5d5e3ca70 100644 --- a/src/os2/menu.cpp +++ b/src/os2/menu.cpp @@ -1,81 +1,110 @@ ///////////////////////////////////////////////////////////////////////////// // Name: menu.cpp // Purpose: wxMenu, wxMenuBar, wxMenuItem -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" -// ============================================================================ -// headers & declarations -// ============================================================================ - -// wxWindows headers -// ----------------- +#ifndef WX_PRECOMP + #include "wx/frame.h" + #include "wx/menu.h" + #include "wx/utils.h" + #include "wx/intl.h" +#endif -#ifdef __GNUG__ -#pragma implementation "menu.h" -#pragma implementation "menuitem.h" +#if wxUSE_OWNER_DRAWN + #include "wx/ownerdrw.h" #endif +#include "wx/os2/private.h" #include "wx/menu.h" #include "wx/menuitem.h" #include "wx/log.h" -#include "wx/utils.h" // other standard headers -// ---------------------- #include +// ---------------------------------------------------------------------------- +// global variables +// ---------------------------------------------------------------------------- + +extern wxMenu *wxCurrentPopupMenu; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// the (popup) menu title has this special id +static const int idMenuTitle = -2; + +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + #if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler) -IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler) + IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler) + IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler) #endif // ============================================================================ // implementation // ============================================================================ -// Menus +// --------------------------------------------------------------------------- +// wxMenu construction, adding and removing menu items +// --------------------------------------------------------------------------- // Construct a menu with optional title (then use append) -wxMenu::wxMenu(const wxString& title, const wxFunction func) +void wxMenu::Init(const wxString& title, const wxFunction func ) { m_title = title; m_parent = NULL; m_eventHandler = this; + m_pInvokingWindow = NULL; + m_doBreak = FALSE ; m_noItems = 0; m_menuBar = NULL; + m_hMenu = 0; //(WXHMENU) CreatePopupMenu(); + m_savehMenu = 0 ; + m_topLevelMenu = this; m_clientData = (void*) NULL; - if (m_title != "") + + if ( !!m_title ) { - Append(-2, m_title) ; + Append(idMenuTitle, m_title) ; AppendSeparator() ; } Callback(func); - - // TODO create menu } // The wxWindow destructor will take care of deleting the submenus. wxMenu::~wxMenu() { - // TODO destroy menu and children + // free Windows resources + if ( m_hMenu ) + { +// ::DestroyMenu((HMENU)m_hMenu); + m_hMenu = 0; + } + // delete submenus wxNode *node = m_menuItems.First(); - while (node) + while ( node ) { wxMenuItem *item = (wxMenuItem *)node->Data(); // Delete child menus. // Beware: they must not be appended to children list!!! // (because order of delete is significant) - if (item->GetSubMenu()) + if ( item->IsSubMenu() ) item->DeleteSubMenu(); wxNode *next = node->Next(); @@ -87,374 +116,669 @@ wxMenu::~wxMenu() void wxMenu::Break() { - // TODO + m_doBreak = TRUE; } // function appends a new item or submenu to the menu void wxMenu::Append(wxMenuItem *pItem) { - // TODO + wxCHECK_RET( pItem != NULL, wxT("can't append NULL item to the menu") ); + +#if wxUSE_ACCEL + // check for accelerators: they are given after '\t' + wxString label = pItem->GetName(); + int posTab = label.Find(wxT('\t')); + if ( posTab != wxNOT_FOUND ) { + // parse the accelerator string + int keyCode = 0; + int accelFlags = wxACCEL_NORMAL; + wxString current; + for ( size_t n = (size_t)posTab + 1; n < label.Len(); n++ ) { + if ( (label[n] == '+') || (label[n] == '-') ) { + if ( current == _("ctrl") ) + accelFlags |= wxACCEL_CTRL; + else if ( current == _("alt") ) + accelFlags |= wxACCEL_ALT; + else if ( current == _("shift") ) + accelFlags |= wxACCEL_SHIFT; + else { + wxLogDebug(wxT("Unknown accel modifier: '%s'"), + current.c_str()); + } + + current.Empty(); + } + else { + current += wxTolower(label[n]); + } + } + + if ( current.IsEmpty() ) { + wxLogDebug(wxT("No accel key found, accel string ignored.")); + } + else { + if ( current.Len() == 1 ) { + // it's a letter + keyCode = wxToupper(current[0U]); + } + else { + // it should be a function key + if ( current[0U] == 'f' && isdigit(current[1U]) && + (current.Len() == 2 || + (current.Len() == 3 && isdigit(current[2U]))) ) { + int n; + wxSscanf(current.c_str() + 1, wxT("%d"), &n); + + keyCode = VK_F1 + n - 1; + } + else { + wxLogDebug(wxT("Unrecognized accel key '%s', accel " + "string ignored."), current.c_str()); + } + } + } + + if ( keyCode ) { + // do add an entry + m_accelKeyCodes.Add(keyCode); + m_accelFlags.Add(accelFlags); + m_accelIds.Add(pItem->GetId()); + } + } +#endif // wxUSE_ACCEL - wxCHECK_RET( pItem != NULL, "can't append NULL item to the menu" ); + UINT flags = 0; - m_menuItems.Append(pItem); + // TODO: +/* + // if "Break" has just been called, insert a menu break before this item + // (and don't forget to reset the flag) + if ( m_doBreak ) { + flags |= MF_MENUBREAK; + m_doBreak = FALSE; + } - m_noItems++; + if ( pItem->IsSeparator() ) { + flags |= MF_SEPARATOR; + } + + // id is the numeric id for normal menu items and HMENU for submenus as + // required by ::AppendMenu() API + UINT id; + wxMenu *submenu = pItem->GetSubMenu(); + if ( submenu != NULL ) { + wxASSERT( submenu->GetHMenu() != (WXHMENU) NULL ); + + id = (UINT)submenu->GetHMenu(); + submenu->m_topLevelMenu = m_topLevelMenu; + submenu->m_parent = this; + submenu->m_savehMenu = (WXHMENU)id; + submenu->m_hMenu = 0; + + flags |= MF_POPUP; + } + else { + id = pItem->GetId(); + } + + const char* pData; + +#if wxUSE_OWNER_DRAWN + if ( pItem->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages? + // item draws itself, pass pointer to it in data parameter + flags |= MF_OWNERDRAW; + pData = (const char*)pItem; + } + else +#endif + { + // menu is just a normal string (passed in data parameter) + flags |= MF_STRING; + pData = label; + } + if ( !::AppendMenu(GetHmenu(), flags, id, pData) ) + { + wxLogLastError("AppendMenu"); + } + else + { + if ( id == idMenuTitle ) + { + // visually select the menu title + MENUITEMINFO mii; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = MFS_DEFAULT; + + if ( !SetMenuItemInfo(GetHmenu(), (unsigned)id, FALSE, &mii) ) + { + wxLogLastError(wxT("SetMenuItemInfo")); + } + } + m_menuItems.Append(pItem); + m_noItems++; + } +*/ } void wxMenu::AppendSeparator() { - // TODO Append(new wxMenuItem(this, ID_SEPARATOR)); } // Pullright item -void wxMenu::Append(int Id, const wxString& label, wxMenu *SubMenu, +void wxMenu::Append(int id, + const wxString& label, + wxMenu *SubMenu, const wxString& helpString) { - Append(new wxMenuItem(this, Id, label, helpString, FALSE, SubMenu)); + Append(new wxMenuItem(this, id, label, helpString, FALSE, SubMenu)); } // Ordinary menu item -void wxMenu::Append(int Id, const wxString& label, - const wxString& helpString, bool checkable) +void wxMenu::Append(int id, + const wxString& label, + const wxString& helpString, + bool checkable) { - // 'checkable' parameter is useless for Windows. - Append(new wxMenuItem(this, Id, label, helpString, checkable)); + // 'checkable' parameter is useless for Windows. + Append(new wxMenuItem(this, id, label, helpString, checkable)); } +// delete item by id void wxMenu::Delete(int id) { - wxNode *node; - wxMenuItem *item; + wxMenuItem *item = NULL; int pos; - - for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) { - item = (wxMenuItem *)node->Data(); - if (item->GetId() == id) - break; + wxNode *node; + for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) + { + item = (wxMenuItem *)node->Data(); + if ( item->GetId() == id ) + break; } - if (!node) - return; + wxCHECK_RET( node, wxT("wxMenu::Delete(): item doesn't exist") ); + + HMENU menu = GetHmenu(); + + wxMenu *pSubMenu = item->GetSubMenu(); + if ( pSubMenu != NULL ) + { +// RemoveMenu(menu, (UINT)pos, MF_BYPOSITION); + pSubMenu->m_hMenu = pSubMenu->m_savehMenu; + pSubMenu->m_savehMenu = 0; + pSubMenu->m_parent = NULL; + // RemoveChild(item->subMenu); + pSubMenu->m_topLevelMenu = NULL; + // TODO: Why isn't subMenu deleted here??? + // Will put this in for now. Assuming this is supposed + // to delete the menu, not just remove it. + item->DeleteSubMenu(); + } +// else +// { +// DeleteMenu(menu, (UINT)pos, MF_BYPOSITION); +// } m_menuItems.DeleteNode(node); delete item; +} - // TODO +#if wxUSE_ACCEL + +// --------------------------------------------------------------------------- +// accelerator helpers +// --------------------------------------------------------------------------- + +// create the wxAcceleratorEntries for our accels and put them into provided +// array - return the number of accels we have +size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const +{ + size_t count = GetAccelCount(); + for ( size_t n = 0; n < count; n++ ) + { + (*accels++).Set(m_accelFlags[n], m_accelKeyCodes[n], m_accelIds[n]); + } + + return count; } -void wxMenu::Enable(int Id, bool Flag) +#endif // wxUSE_ACCEL + +// --------------------------------------------------------------------------- +// wxMenu functions implemented in wxMenuItem +// --------------------------------------------------------------------------- + +void wxMenu::Enable(int id, bool Flag) { - wxMenuItem *item = FindItemForId(Id); - wxCHECK_RET( item != NULL, "can't enable non-existing menu item" ); + wxMenuItem *item = FindItemForId(id); + wxCHECK_RET( item != NULL, wxT("can't enable non-existing menu item") ); item->Enable(Flag); } -bool wxMenu::Enabled(int Id) const +bool wxMenu::IsEnabled(int id) const { - wxMenuItem *item = FindItemForId(Id); - wxCHECK( item != NULL, FALSE ); + wxMenuItem *item = FindItemForId(id); + wxCHECK_MSG( item != NULL, FALSE, wxT("invalid item id") ); return item->IsEnabled(); } -void wxMenu::Check(int Id, bool Flag) +void wxMenu::Check(int id, bool Flag) { - wxMenuItem *item = FindItemForId(Id); - wxCHECK_RET( item != NULL, "can't get status of non-existing menu item" ); + wxMenuItem *item = FindItemForId(id); + wxCHECK_RET( item != NULL, wxT("can't get status of non-existing menu item") ); item->Check(Flag); } -bool wxMenu::Checked(int Id) const +bool wxMenu::IsChecked(int id) const { - wxMenuItem *item = FindItemForId(Id); - wxCHECK( item != NULL, FALSE ); + wxMenuItem *item = FindItemForId(id); + wxCHECK_MSG( item != NULL, FALSE, wxT("invalid item id") ); return item->IsChecked(); } -void wxMenu::SetTitle(const wxString& label) +void wxMenu::SetLabel(int id, const wxString& label) { - m_title = label ; - // TODO + wxMenuItem *item = FindItemForId(id) ; + wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") ); + + item->SetName(label); } -const wxString wxMenu::GetTitle() const +wxString wxMenu::GetLabel(int id) const { - return m_title; + wxString label; + wxMenuItem *pItem = FindItemForId(id) ; + if (pItem) + label = pItem->GetName() ; + else + wxFAIL_MSG(wxT("wxMenu::GetLabel: item doesn't exist")); + + return label; } -void wxMenu::SetLabel(int id, const wxString& label) +void wxMenu::SetHelpString(int itemId, const wxString& helpString) { - wxMenuItem *item = FindItemForId(id) ; - if (item==NULL) - return; - - if (item->GetSubMenu()==NULL) - { - // TODO - } + wxMenuItem *item = FindItemForId (itemId); + if (item) + item->SetHelp(helpString); else - { - // TODO - } - item->SetName(label); + wxFAIL_MSG(wxT("wxMenu::SetHelpString: item doesn't exist")); } -wxString wxMenu::GetLabel(int Id) const +wxString wxMenu::GetHelpString (int itemId) const { - // TODO - return wxString("") ; + wxString help; + wxMenuItem *item = FindItemForId (itemId); + if (item) + help = item->GetHelp(); + else + wxFAIL_MSG(wxT("wxMenu::GetHelpString: item doesn't exist")); + + return help; } -// Finds the item id matching the given string, -1 if not found. -int wxMenu::FindItem (const wxString& itemString) const +// --------------------------------------------------------------------------- +// wxMenu title +// --------------------------------------------------------------------------- + +void wxMenu::SetTitle(const wxString& label) { - char buf1[200]; - char buf2[200]; - wxStripMenuCodes ((char *)(const char *)itemString, buf1); + bool hasNoTitle = m_title.IsEmpty(); + m_title = label; - for (wxNode * node = m_menuItems.First (); node; node = node->Next ()) + HMENU hMenu = GetHmenu(); +// TODO +/* + if ( hasNoTitle ) { - wxMenuItem *item = (wxMenuItem *) node->Data (); - if (item->GetSubMenu()) - { - int ans = item->GetSubMenu()->FindItem(itemString); - if (ans > -1) - return ans; - } - if ( !item->IsSeparator() ) - { - wxStripMenuCodes((char *)item->GetName().c_str(), buf2); - if (strcmp(buf1, buf2) == 0) - return item->GetId(); - } + if ( !label.IsEmpty() ) + { + if ( !InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING, + (unsigned)idMenuTitle, m_title) || + !InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) ) + { + wxLogLastError(wxT("InsertMenu")); + } + } } - - return -1; -} - -wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const -{ - if (itemMenu) - *itemMenu = NULL; - for (wxNode * node = m_menuItems.First (); node; node = node->Next ()) + else { - wxMenuItem *item = (wxMenuItem *) node->Data (); - - if (item->GetId() == itemId) + if ( label.IsEmpty() ) { - if (itemMenu) - *itemMenu = (wxMenu *) this; - return item; + // remove the title and the separator after it + if ( !RemoveMenu(hMenu, 0, MF_BYPOSITION) || + !RemoveMenu(hMenu, 0, MF_BYPOSITION) ) + { + wxLogLastError("RemoveMenu"); + } } - - if (item->GetSubMenu()) + else { - wxMenuItem *ans = item->GetSubMenu()->FindItemForId (itemId, itemMenu); - if (ans) - return ans; + // modify the title + if ( !ModifyMenu(hMenu, 0u, + MF_BYPOSITION | MF_STRING, + (unsigned)idMenuTitle, m_title) ) + { + wxLogLastError("ModifyMenu"); + } } } - if (itemMenu) - *itemMenu = NULL; - return NULL; + // put the title string in bold face + if ( !m_title.IsEmpty() ) + { + MENUITEMINFO mii; + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE; + mii.fState = MFS_DEFAULT; + + if ( !SetMenuItemInfo(hMenu, (unsigned)idMenuTitle, FALSE, &mii) ) + { + wxLogLastError("SetMenuItemInfo"); + } + } +*/ } -void wxMenu::SetHelpString(int itemId, const wxString& helpString) +const wxString wxMenu::GetTitle() const { - wxMenuItem *item = FindItemForId (itemId); - if (item) - item->SetHelp(helpString); + return m_title; } -wxString wxMenu::GetHelpString (int itemId) const +// --------------------------------------------------------------------------- +// event processing +// --------------------------------------------------------------------------- + +bool wxMenu::OS2Command(WXUINT WXUNUSED(param), WXWORD id) { - wxMenuItem *item = FindItemForId (itemId); - wxString str(""); - return (item == NULL) ? str : item->GetHelp(); + // ignore commands from the menu title + + if ( id != (WXWORD)idMenuTitle ) + { + wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED); + event.SetEventObject( this ); + event.SetId( id ); + event.SetInt( id ); + ProcessCommand(event); + } + + return TRUE; } -void wxMenu::ProcessCommand(wxCommandEvent & event) +bool wxMenu::ProcessCommand(wxCommandEvent & event) { bool processed = FALSE; // Try a callback if (m_callback) { - (void) (*(m_callback)) (*this, event); - processed = TRUE; + (void)(*(m_callback))(*this, event); + processed = TRUE; } // Try the menu's event handler if ( !processed && GetEventHandler()) { - processed = GetEventHandler()->ProcessEvent(event); + processed = GetEventHandler()->ProcessEvent(event); } -/* TODO - // Try the window the menu was popped up from (and up - // through the hierarchy) - if ( !processed && GetInvokingWindow()) - processed = GetInvokingWindow()->ProcessEvent(event); -*/ + + // Try the window the menu was popped up from (and up through the + // hierarchy) + wxWindow *win = GetInvokingWindow(); + if ( !processed && win ) + processed = win->GetEventHandler()->ProcessEvent(event); + + return processed; } -// Update a menu and all submenus recursively. -// source is the object that has the update event handlers -// defined for it. If NULL, the menu or associated window -// will be used. -void wxMenu::UpdateUI(wxEvtHandler* source) -{ - if (!source && GetInvokingWindow()) - source = GetInvokingWindow()->GetEventHandler(); - if (!source) - source = GetEventHandler(); - if (!source) - source = this; +// --------------------------------------------------------------------------- +// Item search +// --------------------------------------------------------------------------- - wxNode* node = GetItems().First(); - while (node) - { - wxMenuItem* item = (wxMenuItem*) node->Data(); - if ( !item->IsSeparator() ) +// Finds the item id matching the given string, -1 if not found. +int wxMenu::FindItem (const wxString& itemString) const +{ + wxString itemLabel = wxStripMenuCodes(itemString); + for ( wxNode *node = m_menuItems.First(); node; node = node->Next() ) { - wxWindowID id = item->GetId(); - wxUpdateUIEvent event(id); - event.SetEventObject( source ); + wxMenuItem *item = (wxMenuItem *)node->Data(); + if ( item->IsSubMenu() ) + { + int ans = item->GetSubMenu()->FindItem(itemString); + if ( ans != wxNOT_FOUND ) + return ans; + } + else if ( !item->IsSeparator() ) + { + wxString label = wxStripMenuCodes(item->GetName()); + if ( itemLabel == label ) + return item->GetId(); + } + } - if (source->ProcessEvent(event)) - { - if (event.GetSetText()) - SetLabel(id, event.GetText()); - if (event.GetSetChecked()) - Check(id, event.GetChecked()); - if (event.GetSetEnabled()) - Enable(id, event.GetEnabled()); - } + return wxNOT_FOUND; +} - if (item->GetSubMenu()) - item->GetSubMenu()->UpdateUI(source); +wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const +{ + if ( itemMenu ) + *itemMenu = NULL; + + wxMenuItem *item = NULL; + for ( wxNode *node = m_menuItems.First(); node && !item; node = node->Next() ) + { + item = (wxMenuItem *)node->Data(); + + if ( item->GetId() == itemId ) + { + if (itemMenu) + *itemMenu = (wxMenu *)this; + } + else if ( item->IsSubMenu() ) + { + item = item->GetSubMenu()->FindItemForId(itemId, itemMenu); + } + else + { + // don't exit the loop + item = NULL; + } } - node = node->Next(); - } + + return item; } -bool wxWindow::PopupMenu(wxMenu *menu, int x, int y) +// --------------------------------------------------------------------------- +// other +// --------------------------------------------------------------------------- + +void wxMenu::Attach(wxMenuBar *menubar) { - menu->SetInvokingWindow(this); - menu->UpdateUI(); + // menu can be in at most one menubar because otherwise they would both + // delete the menu pointer + wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") ); - // TODO - return FALSE; + m_menuBar = menubar; + m_savehMenu = m_hMenu; + m_hMenu = 0; +} + +void wxMenu::Detach() +{ + wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") ); + + m_hMenu = m_savehMenu; + m_savehMenu = 0; } +// --------------------------------------------------------------------------- // Menu Bar -wxMenuBar::wxMenuBar() +// --------------------------------------------------------------------------- + +void wxMenuBar::Init() { m_eventHandler = this; m_menuCount = 0; m_menus = NULL; m_titles = NULL; m_menuBarFrame = NULL; + m_hMenu = 0; +} - // TODO +wxMenuBar::wxMenuBar() +{ + Init(); } -wxMenuBar::wxMenuBar(int n, wxMenu *menus[], const wxString titles[]) +wxMenuBar::wxMenuBar( long WXUNUSED(style) ) { - m_eventHandler = this; - m_menuCount = n; + Init(); +} + +wxMenuBar::wxMenuBar(int count, wxMenu *menus[], const wxString titles[]) +{ + Init(); + + m_menuCount = count; m_menus = menus; - m_titles = new wxString[n]; + m_titles = new wxString[count]; + int i; - for ( i = 0; i < n; i++ ) - m_titles[i] = titles[i]; - m_menuBarFrame = NULL; + for ( i = 0; i < count; i++ ) + m_titles[i] = titles[i]; - // TODO + for ( i = 0; i < count; i++ ) + m_menus[i]->Attach(this); } wxMenuBar::~wxMenuBar() { - int i; - for (i = 0; i < m_menuCount; i++) + for ( int i = 0; i < m_menuCount; i++ ) { delete m_menus[i]; } + delete[] m_menus; delete[] m_titles; +} - // TODO +// --------------------------------------------------------------------------- +// wxMenuBar helpers +// --------------------------------------------------------------------------- + +void wxMenuBar::Refresh() +{ + wxCHECK_RET( m_menuBarFrame, wxT("can't refresh a menubar withotu a frame") ); + +// TODO DrawMenuBar((HWND)m_menuBarFrame->GetHWND()) ; +} + +WXHMENU wxMenuBar::Create() +{ + if (m_hMenu != 0 ) + return m_hMenu; + + wxCHECK_MSG( !m_hMenu, TRUE, wxT("menubar already created") ); + + m_hMenu = 0; // TODO: (WXHMENU)::CreateMenu(); + + if ( !m_hMenu ) + { + wxLogLastError("CreateMenu"); + } + else + { + for ( int i = 0; i < m_menuCount; i++ ) + { +// if ( !::AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING, +// (UINT)m_menus[i]->GetHMenu(), +// m_titles[i]) ) +// { +// wxLogLastError("AppendMenu"); +// } + } + } + + return m_hMenu; } +// --------------------------------------------------------------------------- +// wxMenuBar functions forwarded to wxMenuItem +// --------------------------------------------------------------------------- + // Must only be used AFTER menu has been attached to frame, // otherwise use individual menus to enable/disable items -void wxMenuBar::Enable(int id, bool flag) +void wxMenuBar::Enable(int id, bool enable) { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(id, &itemMenu) ; - if (!item) - return; - // TODO + wxCHECK_RET( item, wxT("attempt to enable an item which doesn't exist") ); + + item->Enable(enable); } -void wxMenuBar::EnableTop(int pos, bool flag) +void wxMenuBar::EnableTop(int pos, bool enable) { - // TODO + int flag = 0; // TODO enable ? MF_ENABLED : MF_GRAYED;; + +// EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag); } // Must only be used AFTER menu has been attached to frame, // otherwise use individual menus -void wxMenuBar::Check(int id, bool flag) +void wxMenuBar::Check(int id, bool check) { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(id, &itemMenu) ; - if (!item) - return; - if (!item->IsCheckable()) - return ; + wxCHECK_RET( item, wxT("attempt to check an item which doesn't exist") ); + wxCHECK_RET( item->IsCheckable(), wxT("attempt to check an uncheckable item") ); - // TODO + item->Check(check); } -bool wxMenuBar::Checked(int id) const +bool wxMenuBar::IsChecked(int id) const { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(id, &itemMenu) ; - if (!item) - return FALSE; - // TODO + wxCHECK_MSG( item, FALSE, wxT("wxMenuBar::IsChecked(): no such item") ); + +// int flag = ::GetMenuState(GetHmenuOf(itemMenu), id, MF_BYCOMMAND); + +// return (flag & MF_CHECKED) != 0; return FALSE; } -bool wxMenuBar::Enabled(int id) const +bool wxMenuBar::IsEnabled(int id) const { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(id, &itemMenu) ; - if (!item) - return FALSE; - // TODO - return FALSE ; -} + wxCHECK_MSG( item, FALSE, wxT("wxMenuBar::IsEnabled(): no such item") ); +// int flag = ::GetMenuState(GetHmenuOf(itemMenu), id, MF_BYCOMMAND) ; + + // don't "and" with MF_ENABLED because its value is 0 +// return (flag & MF_DISABLED) == 0; + return FALSE; +} void wxMenuBar::SetLabel(int id, const wxString& label) { wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(id, &itemMenu) ; - if (!item) - return; + wxCHECK_RET( item, wxT("wxMenuBar::SetLabel(): no such item") ); - // TODO + item->SetName(label); } wxString wxMenuBar::GetLabel(int id) const @@ -462,36 +786,205 @@ wxString wxMenuBar::GetLabel(int id) const wxMenu *itemMenu = NULL; wxMenuItem *item = FindItemForId(id, &itemMenu) ; - if (!item) - return wxString(""); + wxCHECK_MSG( item, wxT(""), wxT("wxMenuBar::GetLabel(): no such item") ); - // TODO - return wxString("") ; + return item->GetName(); } +void wxMenuBar::SetHelpString (int id, const wxString& helpString) +{ + wxMenu *itemMenu = NULL; + wxMenuItem *item = FindItemForId(id, &itemMenu) ; + + wxCHECK_RET( item, wxT("wxMenuBar::SetHelpString(): no such item") ); + + item->SetHelp(helpString); +} + +wxString wxMenuBar::GetHelpString (int id) const +{ + wxMenu *itemMenu = NULL; + wxMenuItem *item = FindItemForId(id, &itemMenu) ; + + wxCHECK_MSG( item, wxT(""), wxT("wxMenuBar::GetHelpString(): no such item") ); + + return item->GetHelp(); +} + +// --------------------------------------------------------------------------- +// wxMenuBar functions to work with the top level submenus +// --------------------------------------------------------------------------- + +// NB: we don't support owner drawn top level items for now, if we do these +// functions would have to be changed to use wxMenuItem as well + void wxMenuBar::SetLabelTop(int pos, const wxString& label) { - // TODO + UINT id; + UINT flagsOld = 0; // TODO: ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION); + if ( flagsOld == 0xFFFFFFFF ) + { + wxLogLastError(wxT("GetMenuState")); + + return; + } + +// if ( flagsOld & MF_POPUP ) +// { +// // HIBYTE contains the number of items in the submenu in this case +// flagsOld &= 0xff ; +// id = (UINT)::GetSubMenu((HMENU)m_hMenu, pos) ; +// } +// else +// { +// id = pos; +// } + +// if ( ::ModifyMenu(GetHmenu(), pos, MF_BYPOSITION | MF_STRING | flagsOld, +// id, label) == 0xFFFFFFFF ) +// { +// wxLogLastError("ModifyMenu"); +// } } wxString wxMenuBar::GetLabelTop(int pos) const { - // TODO - return wxString(""); + int len = 0; // TODO: ::GetMenuString((HMENU)m_hMenu, pos, NULL, 0, MF_BYCOMMAND); + + len++; // for the NUL character + wxString label; +// ::GetMenuString(GetHmenu(), pos, label.GetWriteBuf(len), len, MF_BYCOMMAND); + label.UngetWriteBuf(); + + return label; } +// --------------------------------------------------------------------------- +// wxMenuBar notifications +// --------------------------------------------------------------------------- + bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos) { + if ( !m_menuBarFrame ) + return TRUE; + // TODO +/* + if ( ::RemoveMenu((HMENU)m_hMenu, (UINT)pos, MF_BYPOSITION) ) + { + // VZ: I'm not sure about what's going on here, so I leave an assert + wxASSERT_MSG( m_menus[pos] == a_menu, wxT("what is this parameter for??") ); + + a_menu->Detach(); + + if ( m_menuBarFrame ) + Refresh(); + + return TRUE; + } + else + { + wxLogLastError("RemoveMenu"); + } +*/ return FALSE; } -bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title) +bool wxMenuBar::OnAppend(wxMenu *a_menu, const wxChar *title) { - // TODO - return FALSE; + WXHMENU submenu = a_menu->GetHMenu(); + if ( !submenu ) + return FALSE; + + if ( !m_menuBarFrame ) + return TRUE; + + a_menu->Attach(this); + +// if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING, +// (UINT)submenu, title) ) +// { +// wxLogLastError(wxT("AppendMenu")); +// } + + Refresh(); + + return TRUE; } +// --------------------------------------------------------------------------- +// wxMenuBar construction +// --------------------------------------------------------------------------- +int wxMenuBar::FindMenu(const wxString& title) +{ + wxString menuTitle = wxStripMenuCodes(title); + for ( int i = 0; i < m_menuCount; i++ ) + { + wxString title = wxStripMenuCodes(m_titles[i]); + if ( menuTitle == title ) + return i; + } + + return wxNOT_FOUND; + +} + + +void wxMenuBar::ReplaceMenu(int pos, wxMenu * new_menu, const wxString& title) +{ + if (m_menuBarFrame) return; + + if ( pos >= 0 && pos < m_menuCount ) + { + wxMenu *old_menu = m_menus[pos]; + m_menus[pos] = new_menu; + delete old_menu; + } + +} + + +void wxMenuBar::Insert(int pos, wxMenu * menu, const wxString& title) +{ + if (m_menuBarFrame) return; + if ( pos < 0 && pos >= m_menuCount ) return; + + m_menuCount ++; + wxMenu **new_menus = new wxMenu *[m_menuCount]; + wxString *new_titles = new wxString[m_menuCount]; + int i; + + for (i = 0; i < pos; i++) + { + new_menus[i] = m_menus[i]; + m_menus[i] = NULL; + new_titles[i] = m_titles[i]; + m_titles[i] = wxT(""); + } + + new_menus[pos] = (wxMenu *)menu; + new_titles[i] = title; + + for (i = pos+1; i < m_menuCount; i++) + { + new_menus[i] = m_menus[i-1]; + m_menus[i-1] = NULL; + new_titles[i] = m_titles[i-1]; + m_titles[i-1] = wxT(""); + } + if (m_menus) + { + delete[]m_menus; + delete[]m_titles; + } + m_menus = new_menus; + m_titles = new_titles; + + menu->SetParent(this); + +} + + void wxMenuBar::Append (wxMenu * menu, const wxString& title) { if (!OnAppend(menu, title)) @@ -503,11 +996,11 @@ void wxMenuBar::Append (wxMenu * menu, const wxString& title) int i; for (i = 0; i < m_menuCount - 1; i++) - { + { new_menus[i] = m_menus[i]; m_menus[i] = NULL; new_titles[i] = m_titles[i]; - m_titles[i] = ""; + m_titles[i] = wxT(""); } if (m_menus) { @@ -520,7 +1013,7 @@ void wxMenuBar::Append (wxMenu * menu, const wxString& title) m_menus[m_menuCount - 1] = (wxMenu *)menu; m_titles[m_menuCount - 1] = title; - // TODO + menu->SetParent(this); } void wxMenuBar::Delete(wxMenu * menu, int i) @@ -528,17 +1021,14 @@ void wxMenuBar::Delete(wxMenu * menu, int i) int j; int ii = (int) i; - if (menu != 0) - { - for (ii = 0; ii < m_menuCount; ii++) - { + if (menu != 0) { + for (ii = 0; ii < m_menuCount; ii++) { if (m_menus[ii] == menu) - break; - } + break; + } if (ii >= m_menuCount) return; - } else - { + } else { if (ii < 0 || ii >= m_menuCount) return; menu = m_menus[ii]; @@ -550,65 +1040,149 @@ void wxMenuBar::Delete(wxMenu * menu, int i) menu->SetParent(NULL); -- m_menuCount; - for (j = ii; j < m_menuCount; j++) - { + for (j = ii; j < m_menuCount; j++) { m_menus[j] = m_menus[j + 1]; m_titles[j] = m_titles[j + 1]; } } -// Find the menu menuString, item itemString, and return the item id. -// Returns -1 if none found. -int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemString) const +void wxMenuBar::Attach(wxFrame *frame) { - char buf1[200]; - char buf2[200]; - wxStripMenuCodes ((char *)(const char *)menuString, buf1); + wxASSERT_MSG( !m_menuBarFrame, wxT("menubar already attached!") ); + + m_menuBarFrame = frame; + +#if wxUSE_ACCEL + // create the accel table - we consider that the menubar construction is + // finished + size_t nAccelCount = 0; int i; - for (i = 0; i < m_menuCount; i++) + for ( i = 0; i < m_menuCount; i++ ) + { + nAccelCount += m_menus[i]->GetAccelCount(); + } + + if ( nAccelCount ) { - wxStripMenuCodes ((char *)(const char *)m_titles[i], buf2); - if (strcmp (buf1, buf2) == 0) - return m_menus[i]->FindItem (itemString); + wxAcceleratorEntry *accelEntries = new wxAcceleratorEntry[nAccelCount]; + + nAccelCount = 0; + for ( i = 0; i < m_menuCount; i++ ) + { + nAccelCount += m_menus[i]->CopyAccels(&accelEntries[nAccelCount]); + } + + m_accelTable = wxAcceleratorTable(nAccelCount, accelEntries); + + delete [] accelEntries; } - return -1; +#endif // wxUSE_ACCEL } -wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const +void wxMenuBar::Detach() { - if (itemMenu) +// ::DestroyMenu((HMENU)m_hMenu); + m_hMenu = NULL; + m_menuBarFrame = NULL; +} + + +// --------------------------------------------------------------------------- +// wxMenuBar searching for menu items +// --------------------------------------------------------------------------- + +// Find the itemString in menuString, and return the item id or wxNOT_FOUND +int wxMenuBar::FindMenuItem(const wxString& menuString, + const wxString& itemString) const +{ + wxString menuLabel = wxStripMenuCodes(menuString); + for ( int i = 0; i < m_menuCount; i++ ) + { + wxString title = wxStripMenuCodes(m_titles[i]); + if ( menuString == title ) + return m_menus[i]->FindItem(itemString); + } + + return wxNOT_FOUND; +} + +wxMenuItem *wxMenuBar::FindItemForId (int id, wxMenu **itemMenu) const +{ + if ( itemMenu ) *itemMenu = NULL; wxMenuItem *item = NULL; - int i; - for (i = 0; i < m_menuCount; i++) - if ((item = m_menus[i]->FindItemForId (Id, itemMenu))) - return item; + for ( int i = 0; !item && (i < m_menuCount); i++ ) + { + item = m_menus[i]->FindItemForId(id, itemMenu); + } + + return item; +} + + +// ---------------------------------------------------------------------------- +// helper functions +// ---------------------------------------------------------------------------- + +wxWindow *wxMenu::GetWindow() const +{ + if ( m_pInvokingWindow != NULL ) + return m_pInvokingWindow; + else if ( m_menuBar != NULL) + return m_menuBar->GetFrame(); + return NULL; } -void wxMenuBar::SetHelpString (int Id, const wxString& helpString) +WXHMENU wxMenu::GetHMenu() const { - int i; - for (i = 0; i < m_menuCount; i++) - { - if (m_menus[i]->FindItemForId (Id)) - { - m_menus[i]->SetHelpString (Id, helpString); - return; - } - } + if ( m_hMenu != 0 ) + return m_hMenu; + else if ( m_savehMenu != 0 ) + return m_savehMenu; + + wxFAIL_MSG(wxT("wxMenu without HMENU")); + + return 0; } -wxString wxMenuBar::GetHelpString (int Id) const +// Update a menu and all submenus recursively. source is the object that has +// the update event handlers defined for it. If NULL, the menu or associated +// window will be used. +void wxMenu::UpdateUI(wxEvtHandler* source) { - int i; - for (i = 0; i < m_menuCount; i++) + if (!source && GetInvokingWindow()) + source = GetInvokingWindow()->GetEventHandler(); + if (!source) + source = GetEventHandler(); + if (!source) + source = this; + + wxNode* node = GetItems().First(); + while (node) { - if (m_menus[i]->FindItemForId (Id)) - return wxString(m_menus[i]->GetHelpString (Id)); + wxMenuItem* item = (wxMenuItem*) node->Data(); + if ( !item->IsSeparator() ) + { + wxWindowID id = item->GetId(); + wxUpdateUIEvent event(id); + event.SetEventObject( source ); + + if (source->ProcessEvent(event)) + { + if (event.GetSetText()) + SetLabel(id, event.GetText()); + if (event.GetSetChecked()) + Check(id, event.GetChecked()); + if (event.GetSetEnabled()) + Enable(id, event.GetEnabled()); + } + + if (item->GetSubMenu()) + item->GetSubMenu()->UpdateUI(source); + } + node = node->Next(); } - return wxString(""); } - diff --git a/src/os2/menuitem.cpp b/src/os2/menuitem.cpp index 38d31737e7..1c1353c558 100644 --- a/src/os2/menuitem.cpp +++ b/src/os2/menuitem.cpp @@ -1,11 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// // Name: menuitem.cpp // Purpose: wxMenuItem implementation -// Author: AUTHOR -// Modified by: -// Created: ??/??/98 +// Author: David Webster +// Modified by: +// Created: 10/10/98 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR +// Copyright: (c) David Webster // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -13,8 +13,31 @@ // headers & declarations // ============================================================================ -#include "wx/menu.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/font.h" + #include "wx/bitmap.h" + #include "wx/settings.h" + #include "wx/font.h" + #include "wx/window.h" + #include "wx/accel.h" + #include "wx/menu.h" + #include "wx/string.h" +#endif + +#include "wx/ownerdrw.h" #include "wx/menuitem.h" +#include "wx/log.h" + +#include "wx/os2/private.h" + +// --------------------------------------------------------------------------- +// convenience macro +// --------------------------------------------------------------------------- + +#define GetHMenuOf(menu) ((HMENU)menu->GetHMenu()) // ============================================================================ // implementation @@ -24,8 +47,13 @@ // dynamic classes implementation // ---------------------------------------------------------------------------- -#if !USE_SHARED_LIBRARY +#if !defined(USE_SHARED_LIBRARY) || !USE_SHARED_LIBRARY +#if wxUSE_OWNER_DRAWN + IMPLEMENT_DYNAMIC_CLASS2(wxMenuItem, wxObject, wxOwnerDrawn) +#else //!USE_OWNER_DRAWN IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject) +#endif //USE_OWNER_DRAWN + #endif //USE_SHARED_LIBRARY // ---------------------------------------------------------------------------- @@ -39,32 +67,55 @@ wxMenuItem::wxMenuItem(wxMenu *pParentMenu, int id, const wxString& strName, const wxString& strHelp, bool bCheckable, wxMenu *pSubMenu) : +#if wxUSE_OWNER_DRAWN + wxOwnerDrawn(strName, bCheckable), +#else //no owner drawn support m_bCheckable(bCheckable), m_strName(strName), +#endif //owner drawn m_strHelp(strHelp) { - wxASSERT( pParentMenu != NULL ); + wxASSERT_MSG( pParentMenu != NULL, wxT("a menu item should have a parent") ); + +#if wxUSE_OWNER_DRAWN + // set default menu colors + #define SYS_COLOR(c) (wxSystemSettings::GetSystemColour(wxSYS_COLOUR_##c)) + + SetTextColour(SYS_COLOR(MENUTEXT)); + SetBackgroundColour(SYS_COLOR(MENU)); + + // we don't want normal items be owner-drawn + ResetOwnerDrawn(); + + #undef SYS_COLOR +#endif - m_pParentMenu = pParentMenu; - m_pSubMenu = pSubMenu; - m_idItem = id; - m_bEnabled = TRUE; + m_pParentMenu = pParentMenu; + m_pSubMenu = pSubMenu; + m_bEnabled = TRUE; + m_bChecked = FALSE; + m_idItem = id; } -wxMenuItem::~wxMenuItem() +wxMenuItem::~wxMenuItem() { } // misc // ---- +// return the id for calling Win32 API functions +int wxMenuItem::GetRealId() const +{ + return m_pSubMenu ? (int)m_pSubMenu->GetHMenu() : GetId(); +} + // delete the sub menu +// ------------------- void wxMenuItem::DeleteSubMenu() { - wxASSERT( m_pSubMenu != NULL ); - - delete m_pSubMenu; - m_pSubMenu = NULL; + delete m_pSubMenu; + m_pSubMenu = NULL; } // change item state @@ -72,24 +123,93 @@ void wxMenuItem::DeleteSubMenu() void wxMenuItem::Enable(bool bDoEnable) { - if ( m_bEnabled != bDoEnable ) { - if ( m_pSubMenu == NULL ) { // normal menu item - // TODO + // TODO: +/* + if ( m_bEnabled != bDoEnable ) { + long rc = EnableMenuItem(GetHMenuOf(m_pParentMenu), + GetRealId(), + MF_BYCOMMAND | + (bDoEnable ? MF_ENABLED : MF_GRAYED)); + + if ( rc == -1 ) { + wxLogLastError("EnableMenuItem"); + } + + m_bEnabled = bDoEnable; } - else // submenu - { - // TODO - } - - m_bEnabled = bDoEnable; - } +*/ } void wxMenuItem::Check(bool bDoCheck) { - wxCHECK_RET( IsCheckable(), "only checkable items may be checked" ); + wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") ); + + // TODO: +/* + if ( m_bChecked != bDoCheck ) { + long rc = CheckMenuItem(GetHMenuOf(m_pParentMenu), + GetId(), + MF_BYCOMMAND | + (bDoCheck ? MF_CHECKED : MF_UNCHECKED)); + + if ( rc == -1 ) { + wxLogLastError("CheckMenuItem"); + } + + m_bChecked = bDoCheck; + } +*/ +} + +void wxMenuItem::SetName(const wxString& strName) +{ + // don't do anything if label didn't change + if ( m_strName == strName ) + return; + + m_strName = strName; + + HMENU hMenu = GetHMenuOf(m_pParentMenu); + + UINT id = GetRealId(); + + // TODO: +/* + UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND); + if ( flagsOld == 0xFFFFFFFF ) + { + wxLogLastError("GetMenuState"); + } + else + { + if ( IsSubMenu() ) + { + // high byte contains the number of items in a submenu for submenus + flagsOld &= 0xFF; + flagsOld |= MF_POPUP; + } + + LPCTSTR data; +#if wxUSE_OWNER_DRAWN + if ( IsOwnerDrawn() ) + { + flagsOld |= MF_OWNERDRAW; + data = (LPCTSTR)this; + } + else +#endif //owner drawn + { + flagsOld |= MF_STRING; + data = strName; + } + + if ( ::ModifyMenu(hMenu, id, + MF_BYCOMMAND | flagsOld, + id, data) == 0xFFFFFFFF ) + { + wxLogLastError(wxT("ModifyMenu")); + } + } +*/ +} - if ( m_bChecked != bDoCheck ) { - // TODO - m_bChecked = bDoCheck; - } diff --git a/src/os2/metafile.cpp b/src/os2/metafile.cpp index 03c29bcb79..3ab444de6b 100644 --- a/src/os2/metafile.cpp +++ b/src/os2/metafile.cpp @@ -1,58 +1,122 @@ ///////////////////////////////////////////////////////////////////////////// // Name: metafile.cpp // Purpose: wxMetaFile, wxMetaFileDC etc. These classes are optional. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: 04/01/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "metafile.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include "wx/setup.h" #endif -#include "wx/object.h" -#include "wx/string.h" -#include "wx/dc.h" -#include "wx/stubs/metafile.h" +#if wxUSE_METAFILE + +#ifndef WX_PRECOMP +#include "wx/utils.h" +#include "wx/app.h" +#endif + +#include "wx/metafile.h" #include "wx/clipbrd.h" +#include "wx/os2/private.h" + +#include +#include extern bool wxClipboardIsOpen; #if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxMetaFile, wxObject) -IMPLEMENT_ABSTRACT_CLASS(wxMetaFileDC, wxDC) +IMPLEMENT_DYNAMIC_CLASS(wxMetafile, wxObject) +IMPLEMENT_ABSTRACT_CLASS(wxMetafileDC, wxDC) #endif -wxMetaFile::wxMetaFile(const wxString& file) +/* + * Metafiles + * Currently, the only purpose for making a metafile is to put + * it on the clipboard. + */ + +wxMetafileRefData::wxMetafileRefData(void) +{ + m_metafile = 0; + m_windowsMappingMode = wxMM_ANISOTROPIC; +} + +wxMetafileRefData::~wxMetafileRefData(void) { - // TODO + if (m_metafile) + { +// TODO: DeleteMetaFile((HMETAFILE) m_metafile); + m_metafile = 0; + } } -wxMetaFile::~wxMetaFile() +wxMetafile::wxMetafile(const wxString& file) { - // TODO + m_refData = new wxMetafileRefData; + + M_METAFILEDATA->m_windowsMappingMode = wxMM_ANISOTROPIC; + M_METAFILEDATA->m_metafile = 0; + if (!file.IsNull() && (file.Cmp(wxT("")) == 0)) + M_METAFILEDATA->m_metafile = (WXHANDLE)0; // TODO: GetMetaFile(file); } -bool wxMetaFile::SetClipboard(int width, int height) +wxMetafile::~wxMetafile(void) { +} + +bool wxMetafile::SetClipboard(int width, int height) +{ + if (!m_refData) + return FALSE; + bool alreadyOpen=wxClipboardOpen(); if (!alreadyOpen) { wxOpenClipboard(); if (!wxEmptyClipboard()) return FALSE; } - bool success = wxSetClipboardData(wxDF_METAFILE,this, width,height); + bool success = wxSetClipboardData(wxDF_METAFILE, this, width,height); if (!alreadyOpen) wxCloseClipboard(); return (bool) success; } -bool wxMetaFile::Play(wxDC *dc) +bool wxMetafile::Play(wxDC *dc) { - // TODO - return FALSE; + if (!m_refData) + return FALSE; + + dc->BeginDrawing(); + + // if (dc->GetHDC() && M_METAFILEDATA->m_metafile) + // PlayMetaFile((HDC) dc->GetHDC(), (HMETAFILE) M_METAFILEDATA->m_metafile); + + dc->EndDrawing(); + + return TRUE; +} + +void wxMetafile::SetHMETAFILE(WXHANDLE mf) +{ + if (m_refData) + m_refData = new wxMetafileRefData; + + M_METAFILEDATA->m_metafile = mf; +} + +void wxMetafile::SetWindowsMappingMode(int mm) +{ + if (m_refData) + m_refData = new wxMetafileRefData; + + M_METAFILEDATA->m_windowsMappingMode = mm; } /* @@ -61,41 +125,155 @@ bool wxMetaFile::Play(wxDC *dc) */ // Original constructor that does not takes origin and extent. If you use this, -// *DO* give origin/extent arguments to wxMakeMetaFilePlaceable. -wxMetaFileDC::wxMetaFileDC(const wxString& file) +// *DO* give origin/extent arguments to wxMakeMetafilePlaceable. +wxMetafileDC::wxMetafileDC(const wxString& file) { - // TODO + m_metaFile = NULL; + m_minX = 10000; + m_minY = 10000; + m_maxX = -10000; + m_maxY = -10000; +// m_title = NULL; + + if (!file.IsNull() && wxFileExists(file)) + wxRemoveFile(file); + + // TODO +/* + if (!file.IsNull() && (file != wxT(""))) + m_hDC = (WXHDC) CreateMetaFile(file); + else + m_hDC = (WXHDC) CreateMetaFile(NULL); +*/ + + m_ok = (m_hDC != (WXHDC) 0) ; + + // Actual Windows mapping mode, for future reference. + m_windowsMappingMode = wxMM_TEXT; + + SetMapMode(wxMM_TEXT); // NOTE: does not set HDC mapmode (this is correct) } // New constructor that takes origin and extent. If you use this, don't -// give origin/extent arguments to wxMakeMetaFilePlaceable. -wxMetaFileDC::wxMetaFileDC(const wxString& file, int xext, int yext, int xorg, int yorg) +// give origin/extent arguments to wxMakeMetafilePlaceable. +wxMetafileDC::wxMetafileDC(const wxString& file, int xext, int yext, int xorg, int yorg) { - // TODO + m_minX = 10000; + m_minY = 10000; + m_maxX = -10000; + m_maxY = -10000; + if (file != wxT("") && wxFileExists(file)) wxRemoveFile(file); +// m_hDC = (WXHDC) CreateMetaFile(file); + + m_ok = TRUE; + +// ::SetWindowOrgEx((HDC) m_hDC,xorg,yorg, NULL); +// ::SetWindowExtEx((HDC) m_hDC,xext,yext, NULL); + + // Actual Windows mapping mode, for future reference. + m_windowsMappingMode = wxMM_ANISOTROPIC; + + SetMapMode(wxMM_TEXT); // NOTE: does not set HDC mapmode (this is correct) } -wxMetaFileDC::~wxMetaFileDC() +wxMetafileDC::~wxMetafileDC(void) { + m_hDC = 0; } -void wxMetaFileDC::GetTextExtent(const wxString& string, float *x, float *y, - float *descent, float *externalLeading, wxFont *theFont, bool use16bit) +void wxMetafileDC::GetTextExtent(const wxString& string, long *x, long *y, + long *descent, long *externalLeading, wxFont *theFont, bool use16bit) const { - // TODO + wxFont *fontToUse = theFont; + if (!fontToUse) + fontToUse = (wxFont*) &m_font; + + // TODO: +/* + HDC dc = GetDC(NULL); + + SIZE sizeRect; + TEXTMETRIC tm; + GetTextExtentPoint(dc, WXSTRINGCAST string, wxStrlen(WXSTRINGCAST string), &sizeRect); + GetTextMetrics(dc, &tm); + + ReleaseDC(NULL, dc); + + if ( x ) + *x = sizeRect.cx; + if ( y ) + *y = sizeRect.cy; + if ( descent ) + *descent = tm.tmDescent; + if ( externalLeading ) + *externalLeading = tm.tmExternalLeading; +*/ } -wxMetaFile *wxMetaFileDC::Close() +wxMetafile *wxMetafileDC::Close(void) { - // TODO - return NULL; + SelectOldObjects(m_hDC); + HANDLE mf = 0; // TODO: CloseMetaFile((HDC) m_hDC); + m_hDC = 0; + if (mf) + { + wxMetafile *wx_mf = new wxMetafile; + wx_mf->SetHMETAFILE((WXHANDLE) mf); + wx_mf->SetWindowsMappingMode(m_windowsMappingMode); + return wx_mf; + } + return NULL; } -void wxMetaFileDC::SetMapMode(int mode) +void wxMetafileDC::SetMapMode(int mode) { - // TODO -} + m_mappingMode = mode; -#if 0 +// int pixel_width = 0; +// int pixel_height = 0; +// int mm_width = 0; +// int mm_height = 0; + + float mm2pixelsX = 10.0; + float mm2pixelsY = 10.0; + + switch (mode) + { + case wxMM_TWIPS: + { + m_logicalScaleX = (float)(twips2mm * mm2pixelsX); + m_logicalScaleY = (float)(twips2mm * mm2pixelsY); + break; + } + case wxMM_POINTS: + { + m_logicalScaleX = (float)(pt2mm * mm2pixelsX); + m_logicalScaleY = (float)(pt2mm * mm2pixelsY); + break; + } + case wxMM_METRIC: + { + m_logicalScaleX = mm2pixelsX; + m_logicalScaleY = mm2pixelsY; + break; + } + case wxMM_LOMETRIC: + { + m_logicalScaleX = (float)(mm2pixelsX/10.0); + m_logicalScaleY = (float)(mm2pixelsY/10.0); + break; + } + default: + case wxMM_TEXT: + { + m_logicalScaleX = 1.0; + m_logicalScaleY = 1.0; + break; + } + } + m_windowExtX = 100; + m_windowExtY = 100; +} #ifdef __WIN32__ struct RECT32 @@ -131,41 +309,43 @@ struct mfPLACEABLEHEADER { * and sets the window origin and extent to mimic the wxMM_TEXT mapping mode. * */ - -bool wxMakeMetaFilePlaceable(const wxString& filename, float scale) + +bool wxMakeMetafilePlaceable(const wxString& filename, float scale) { - return wxMakeMetaFilePlaceable(filename, 0, 0, 0, 0, scale, FALSE); + return wxMakeMetafilePlaceable(filename, 0, 0, 0, 0, scale, FALSE); } -bool wxMakeMetaFilePlaceable(const wxString& filename, int x1, int y1, int x2, int y2, float scale, bool useOriginAndExtent) +bool wxMakeMetafilePlaceable(const wxString& filename, int x1, int y1, int x2, int y2, float scale, bool useOriginAndExtent) { +// TODO: the OS/2 PM/MM way to do this +/* // I'm not sure if this is the correct way of suggesting a scale // to the client application, but it's the only way I can find. int unitsPerInch = (int)(576/scale); - + mfPLACEABLEHEADER header; header.key = 0x9AC6CDD7L; header.hmf = 0; - header.bbox.left = (int)(x1); - header.bbox.top = (int)(y1); - header.bbox.right = (int)(x2); - header.bbox.bottom = (int)(y2); + header.bbox.xLeft = (int)(x1); + header.bbox.yTop = (int)(y1); + header.bbox.xRight = (int)(x2); + header.bbox.yBottom = (int)(y2); header.inch = unitsPerInch; header.reserved = 0; - // Calculate checksum + // Calculate checksum WORD *p; mfPLACEABLEHEADER *pMFHead = &header; for (p =(WORD *)pMFHead,pMFHead -> checksum = 0; p < (WORD *)&pMFHead ->checksum; ++p) pMFHead ->checksum ^= *p; - FILE *fd = fopen((char *)(const char *)filename, "rb"); + FILE *fd = fopen(filename.fn_str(), "rb"); if (!fd) return FALSE; - - char tempFileBuf[256]; - wxGetTempFileName("mf", tempFileBuf); - FILE *fHandle = fopen(tempFileBuf, "wb"); + + wxChar tempFileBuf[256]; + wxGetTempFileName(wxT("mf"), tempFileBuf); + FILE *fHandle = fopen(wxConvFile.cWX2MB(tempFileBuf), "wb"); if (!fHandle) return FALSE; fwrite((void *)&header, sizeof(unsigned char), sizeof(mfPLACEABLEHEADER), fHandle); @@ -179,12 +359,12 @@ bool wxMakeMetaFilePlaceable(const wxString& filename, int x1, int y1, int x2, i // Read metafile header and write METAHEADER metaHeader; fread((void *)&metaHeader, sizeof(unsigned char), sizeof(metaHeader), fd); - + if (useOriginAndExtent) metaHeader.mtSize += 15; else metaHeader.mtSize += 5; - + fwrite((void *)&metaHeader, sizeof(unsigned char), sizeof(metaHeader), fHandle); // Write SetMapMode, SetWindowOrigin and SetWindowExt records @@ -211,7 +391,7 @@ bool wxMakeMetaFilePlaceable(const wxString& filename, int x1, int y1, int x2, i extentRecord->rdParm[1] = extentX; fwrite((void *)modeBuffer, sizeof(char), 8, fHandle); - + if (useOriginAndExtent) { fwrite((void *)originBuffer, sizeof(char), 10, fHandle); @@ -232,8 +412,9 @@ bool wxMakeMetaFilePlaceable(const wxString& filename, int x1, int y1, int x2, i wxRemoveFile(filename); wxCopyFile(tempFileBuf, filename); wxRemoveFile(tempFileBuf); +*/ return TRUE; } -#endif +#endif // wxUSE_METAFILE diff --git a/src/os2/minifram.cpp b/src/os2/minifram.cpp index 4f6f5e5fcb..0d2f2c7d11 100644 --- a/src/os2/minifram.cpp +++ b/src/os2/minifram.cpp @@ -1,16 +1,25 @@ ///////////////////////////////////////////////////////////////////////////// // Name: minifram.cpp // Purpose: wxMiniFrame. Optional; identical to wxFrame if not supported. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/10/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "minifram.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#include "wx/window.h" +#include "wx/os2/private.h" + +#ifndef WX_PRECOMP +#include "wx/setup.h" +#include "wx/event.h" +#include "wx/app.h" +#include "wx/utils.h" #endif #include "wx/minifram.h" @@ -19,4 +28,3 @@ IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame, wxFrame) #endif - -- 2.45.2