From: David Webster Date: Mon, 18 Oct 1999 03:30:47 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/d90895ac118ad4546eed7ee4c358a3fe644a1ad7 *** empty log message *** git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4043 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/os2/setup.h b/include/wx/os2/setup.h index 0c84daebef..2e9ba2801a 100644 --- a/include/wx/os2/setup.h +++ b/include/wx/os2/setup.h @@ -30,6 +30,8 @@ // General features // ---------------------------------------------------------------------------- +#define wxUSE_NET_API 1 // Utilize OS/2's UPM netapi's + #define wxUSE_CONFIG 1 // Use wxConfig, with CreateConfig in wxApp diff --git a/include/wx/os2/setup0.h b/include/wx/os2/setup0.h index 0c84daebef..2e9ba2801a 100644 --- a/include/wx/os2/setup0.h +++ b/include/wx/os2/setup0.h @@ -30,6 +30,8 @@ // General features // ---------------------------------------------------------------------------- +#define wxUSE_NET_API 1 // Utilize OS/2's UPM netapi's + #define wxUSE_CONFIG 1 // Use wxConfig, with CreateConfig in wxApp diff --git a/include/wx/os2/stattext.h b/include/wx/os2/stattext.h index aa8eaf229e..bd58678f76 100644 --- a/include/wx/os2/stattext.h +++ b/include/wx/os2/stattext.h @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// // Name: stattext.h // Purpose: wxStaticText class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_STATTEXT_H_ @@ -22,34 +22,41 @@ WXDLLEXPORT_DATA(extern const char*) wxStaticTextNameStr; class WXDLLEXPORT wxStaticText: public wxControl { - DECLARE_DYNAMIC_CLASS(wxStaticText) + DECLARE_DYNAMIC_CLASS(wxStaticText) + public: - inline wxStaticText() { } + inline wxStaticText() { } - inline wxStaticText(wxWindow *parent, wxWindowID id, + inline wxStaticText(wxWindow *parent, wxWindowID id, const wxString& label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxStaticTextNameStr) - { - Create(parent, id, label, pos, size, style, name); - } + { + Create(parent, id, label, pos, size, style, name); + } - bool Create(wxWindow *parent, wxWindowID id, + bool Create(wxWindow *parent, wxWindowID id, const wxString& label, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxStaticTextNameStr); - // accessors - void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - void SetLabel(const wxString&); + // accessors + void SetLabel(const wxString&); + + // overriden base class virtuals + virtual bool AcceptsFocus() const { return FALSE; } + + // callbacks + virtual WXHBRUSH OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, + WXUINT message, WXWPARAM wParam, WXLPARAM lParam); + virtual MRESULT OS2WindowProc(HWND hwnd, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); - // operations - virtual void Command(wxCommandEvent& WXUNUSED(event)) {}; - virtual void ProcessCommand(wxCommandEvent& WXUNUSED(event)) {}; +protected: + virtual wxSize DoGetBestSize(); }; #endif diff --git a/include/wx/os2/statusbr.h b/include/wx/os2/statusbr.h index 28567b19e1..3e8b21e705 100644 --- a/include/wx/os2/statusbr.h +++ b/include/wx/os2/statusbr.h @@ -2,31 +2,25 @@ // Name: statusbr.h // Purpose: native implementation of wxStatusBar. Optional; can use generic // version instead. -// Author: AUTHOR -// Modified by: -// Created: ??/??/98 +// Author: David Webster +// Modified by: +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR +// Copyright: (c) David Webster // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// #ifndef _WX_STATBAR_H_ #define _WX_STATBAR_H_ -#ifdef __GNUG__ -#pragma interface "statbar.h" -#endif - -#include "wx/generic/statusbr.h" - -class WXDLLEXPORT wxStatusBarXX : public wxStatusBar +class WXDLLEXPORT wxStatusBarPM : public wxStatusBar { - DECLARE_DYNAMIC_CLASS(wxStatusBarXX); + DECLARE_DYNAMIC_CLASS(wxStatusBarPM); public: // ctors - wxStatusBarXX(); - wxStatusBarXX(wxWindow *parent, wxWindowID id = -1, long style = wxST_SIZEGRIP); + wxStatusBarPM(); + wxStatusBarPM(wxWindow *parent, wxWindowID id = -1, long style = wxST_SIZEGRIP); // create status line bool Create(wxWindow *parent, wxWindowID id = -1, long style = wxST_SIZEGRIP); @@ -50,4 +44,5 @@ protected: void SetFieldsWidth(); }; -#endif +#endif // _WX_STATBAR_H_ + diff --git a/include/wx/os2/tabctrl.h b/include/wx/os2/tabctrl.h index 80740019b4..524af3ed90 100644 --- a/include/wx/os2/tabctrl.h +++ b/include/wx/os2/tabctrl.h @@ -1,21 +1,17 @@ ///////////////////////////////////////////////////////////////////////////// // Name: tabctrl.h // Purpose: wxTabCtrl class -// Author: AUTHOR +// Author: David Webster // Modified by: // Created: ??/??/98 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_TABCTRL_H_ #define _WX_TABCTRL_H_ -#ifdef __GNUG__ -#pragma interface "tabctrl.h" -#endif - class wxImageList; /* @@ -111,7 +107,10 @@ class WXDLLEXPORT wxTabCtrl: public wxControl // Insert an item bool InsertItem(int item, const wxString& text, int imageId = -1, void* data = NULL); - void Command(wxCommandEvent& event); + virtual bool OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result); + + // Responds to colour changes + void OnSysColourChanged(wxSysColourChangedEvent& event); protected: wxImageList* m_imageList; diff --git a/include/wx/os2/taskbar.h b/include/wx/os2/taskbar.h index 7f4a36b8b4..aa25c67c41 100644 --- a/include/wx/os2/taskbar.h +++ b/include/wx/os2/taskbar.h @@ -2,48 +2,91 @@ // File: taskbar.h // Purpose: Defines wxTaskBarIcon class for manipulating icons on the // task bar. Optional. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////// #ifndef _WX_TASKBAR_H_ #define _WX_TASKBAR_H_ -#ifdef __GNUG__ -#pragma interface "taskbar.h" -#endif - +#include #include #include -class wxTaskBarIcon: public wxObject -{ +class WXDLLEXPORT wxTaskBarIcon: public wxEvtHandler { + DECLARE_DYNAMIC_CLASS(wxTaskBarIcon) public: - wxTaskBarIcon(); - virtual ~wxTaskBarIcon(); + wxTaskBarIcon(void); + virtual ~wxTaskBarIcon(void); // Accessors + inline WXHWND GetHWND() const { return m_hWnd; } + inline bool IsOK() const { return (m_hWnd != 0) ; } + inline bool IsIconInstalled() const { return m_iconAdded; } // Operations bool SetIcon(const wxIcon& icon, const wxString& tooltip = ""); - bool RemoveIcon(); + bool RemoveIcon(void); + bool PopupMenu(wxMenu *menu); //, int x, int y); // Overridables - virtual void OnMouseMove(); - virtual void OnLButtonDown(); - virtual void OnLButtonUp(); - virtual void OnRButtonDown(); - virtual void OnRButtonUp(); - virtual void OnLButtonDClick(); - virtual void OnRButtonDClick(); + virtual void OnMouseMove(wxEvent&); + virtual void OnLButtonDown(wxEvent&); + virtual void OnLButtonUp(wxEvent&); + virtual void OnRButtonDown(wxEvent&); + virtual void OnRButtonUp(wxEvent&); + virtual void OnLButtonDClick(wxEvent&); + virtual void OnRButtonDClick(wxEvent&); + +// Implementation + static wxTaskBarIcon* FindObjectForHWND(WXHWND hWnd); + static void AddObject(wxTaskBarIcon* obj); + static void RemoveObject(wxTaskBarIcon* obj); + static bool RegisterWindowClass(); + static WXHWND CreateTaskBarWindow(); + MRESULT WindowProc( WXHWND hWnd, UINT msg, MPARAM wParam, MPARAM lParam ); // Data members protected: + WXHWND m_hWnd; + bool m_iconAdded; + static wxList sm_taskBarIcons; + static bool sm_registeredClass; + static unsigned int sm_taskbarMsg; + + // non-virtual default event handlers to forward events to the virtuals + void _OnMouseMove(wxEvent&); + void _OnLButtonDown(wxEvent&); + void _OnLButtonUp(wxEvent&); + void _OnRButtonDown(wxEvent&); + void _OnRButtonUp(wxEvent&); + void _OnLButtonDClick(wxEvent&); + void _OnRButtonDClick(wxEvent&); + + DECLARE_EVENT_TABLE() }; +const wxEventType wxEVT_TASKBAR_MOVE = wxEVT_FIRST + 1550; +const wxEventType wxEVT_TASKBAR_LEFT_DOWN = wxEVT_FIRST + 1551; +const wxEventType wxEVT_TASKBAR_LEFT_UP = wxEVT_FIRST + 1552; +const wxEventType wxEVT_TASKBAR_RIGHT_DOWN = wxEVT_FIRST + 1553; +const wxEventType wxEVT_TASKBAR_RIGHT_UP = wxEVT_FIRST + 1554; +const wxEventType wxEVT_TASKBAR_LEFT_DCLICK = wxEVT_FIRST + 1555; +const wxEventType wxEVT_TASKBAR_RIGHT_DCLICK = wxEVT_FIRST + 1556; + +#define EVT_TASKBAR_MOVE(fn) { wxEVT_TASKBAR_MOVE, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL }, +#define EVT_TASKBAR_LEFT_DOWN(fn) { wxEVT_TASKBAR_LEFT_DOWN, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL }, +#define EVT_TASKBAR_LEFT_UP(fn) { wxEVT_TASKBAR_LEFT_UP, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL }, +#define EVT_TASKBAR_RIGHT_DOWN(fn) { wxEVT_TASKBAR_RIGHT_DOWN, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL }, +#define EVT_TASKBAR_RIGHT_UP(fn) { wxEVT_TASKBAR_RIGHT_UP, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL }, +#define EVT_TASKBAR_LEFT_DCLICK(fn) { wxEVT_TASKBAR_LEFT_DCLICK, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL }, +#define EVT_TASKBAR_RIGHT_DCLICK(fn) { wxEVT_TASKBAR_RIGHT_DCLICK, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL }, + + #endif - // _WX_TASKBAR_H_ + // _TASKBAR_H_ + diff --git a/include/wx/os2/textctrl.h b/include/wx/os2/textctrl.h index 09c11e063e..7bf7bdb077 100644 --- a/include/wx/os2/textctrl.h +++ b/include/wx/os2/textctrl.h @@ -1,166 +1,152 @@ ///////////////////////////////////////////////////////////////////////////// // Name: textctrl.h // Purpose: wxTextCtrl class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_TEXTCTRL_H_ #define _WX_TEXTCTRL_H_ -#ifdef __GNUG__ -#pragma interface "textctrl.h" -#endif - -#include "wx/control.h" - -#if wxUSE_IOSTREAMH -#include -#else -#include -#endif - -WXDLLEXPORT_DATA(extern const char*) wxTextCtrlNameStr; -WXDLLEXPORT_DATA(extern const char*) wxEmptyString; - -// Single-line text item -class WXDLLEXPORT wxTextCtrl: public wxControl +class WXDLLEXPORT wxTextCtrl : public wxTextCtrlBase +{ +public: + // creation + // -------- + + wxTextCtrl(); + wxTextCtrl(wxWindow *parent, wxWindowID id, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxTextCtrlNameStr) + { + Create(parent, id, value, pos, size, style, validator, name); + } + + bool Create(wxWindow *parent, wxWindowID id, + const wxString& value = wxEmptyString, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = 0, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = wxTextCtrlNameStr); + + // implement base class pure virtuals + // ---------------------------------- + + virtual wxString GetValue() const; + virtual void SetValue(const wxString& value); + + virtual int GetLineLength(long lineNo) const; + virtual wxString GetLineText(long lineNo) const; + virtual int GetNumberOfLines() const; + + virtual bool IsModified() const; + virtual bool IsEditable() const; + + // If the return values from and to are the same, there is no selection. + virtual void GetSelection(long* from, long* to) const; + + // operations + // ---------- + + // editing + virtual void Clear(); + virtual void Replace(long from, long to, const wxString& value); + virtual void Remove(long from, long to); + + // load the controls contents from the file + virtual bool LoadFile(const wxString& file); + + // clears the dirty flag + virtual void DiscardEdits(); + + // writing text inserts it at the current position, appending always + // inserts it at the end + virtual void WriteText(const wxString& text); + virtual void AppendText(const wxString& text); + + // translate between the position (which is just an index in the text ctrl + // considering all its contents as a single strings) and (x, y) coordinates + // which represent column and line. + virtual long XYToPosition(long x, long y) const; + virtual bool PositionToXY(long pos, long *x, long *y) const; + + virtual void ShowPosition(long pos); + + // Clipboard operations + virtual void Copy(); + virtual void Cut(); + virtual void Paste(); + + virtual bool CanCopy() const; + virtual bool CanCut() const; + virtual bool CanPaste() const; + + // Undo/redo + virtual void Undo(); + virtual void Redo(); + + virtual bool CanUndo() const; + virtual bool CanRedo() const; + + // Insertion point + virtual void SetInsertionPoint(long pos); + virtual void SetInsertionPointEnd(); + virtual long GetInsertionPoint() const; + virtual long GetLastPosition() const; + + virtual void SetSelection(long from, long to); + virtual void SetEditable(bool editable); + + // Implementation from now on + // -------------------------- + + virtual void Command(wxCommandEvent& event); + virtual bool OS2Command(WXUINT param, WXWORD id); + + virtual WXHBRUSH OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, + WXUINT message, WXWPARAM wParam, + WXLPARAM lParam); + + virtual void AdoptAttributesFromHWND(); + virtual void SetupColours(); + + virtual bool AcceptsFocus() const; + + // callbacks + void OnDropFiles(wxDropFilesEvent& event); + void OnChar(wxKeyEvent& event); // Process 'enter' if required -// TODO Some platforms/compilers don't like inheritance from streambuf. + void OnCut(wxCommandEvent& event); + void OnCopy(wxCommandEvent& event); + void OnPaste(wxCommandEvent& event); + void OnUndo(wxCommandEvent& event); + void OnRedo(wxCommandEvent& event); -#if (defined(__BORLANDC__) && !defined(__WIN32__)) || defined(__MWERKS__) -#define NO_TEXT_WINDOW_STREAM -#endif + void OnUpdateCut(wxUpdateUIEvent& event); + void OnUpdateCopy(wxUpdateUIEvent& event); + void OnUpdatePaste(wxUpdateUIEvent& event); + void OnUpdateUndo(wxUpdateUIEvent& event); + void OnUpdateRedo(wxUpdateUIEvent& event); -#ifndef NO_TEXT_WINDOW_STREAM -, public streambuf -#endif +protected: + // call this to increase the size limit (will do nothing if the current + // limit is big enough) + void AdjustSpaceLimit(); -{ - DECLARE_DYNAMIC_CLASS(wxTextCtrl) - -public: - // creation - // -------- - wxTextCtrl(); - inline wxTextCtrl(wxWindow *parent, wxWindowID id, - const wxString& value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxTextCtrlNameStr) -#ifndef NO_TEXT_WINDOW_STREAM - :streambuf() -#endif - { - Create(parent, id, value, pos, size, style, validator, name); - } - - bool Create(wxWindow *parent, wxWindowID id, - const wxString& value = wxEmptyString, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, long style = 0, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxTextCtrlNameStr); - - // accessors - // --------- - virtual wxString GetValue() const ; - virtual void SetValue(const wxString& value); - - virtual int GetLineLength(long lineNo) const; - virtual wxString GetLineText(long lineNo) const; - virtual int GetNumberOfLines() const; - - // operations - // ---------- - virtual void SetSize(int x, int y, int width, int height, int sizeFlags = wxSIZE_AUTO); - - // Clipboard operations - virtual void Copy(); - virtual void Cut(); - virtual void Paste(); - - virtual bool CanCopy() const; - virtual bool CanCut() const; - virtual bool CanPaste() const; - - // Undo/redo - virtual void Undo(); - virtual void Redo(); - - virtual bool CanUndo() const; - virtual bool CanRedo() const; - - virtual void SetInsertionPoint(long pos); - virtual void SetInsertionPointEnd(); - virtual long GetInsertionPoint() const ; - virtual long GetLastPosition() const ; - virtual void Replace(long from, long to, const wxString& value); - virtual void Remove(long from, long to); - virtual void SetSelection(long from, long to); - virtual void SetEditable(bool editable); - - // If the return values from and to are the same, there is no - // selection. - virtual void GetSelection(long* from, long* to) const; - virtual bool IsEditable() const ; - - // streambuf implementation -#ifndef NO_TEXT_WINDOW_STREAM - int overflow(int i); - int sync(); - int underflow(); -#endif - - wxTextCtrl& operator<<(const wxString& s); - wxTextCtrl& operator<<(int i); - wxTextCtrl& operator<<(long i); - wxTextCtrl& operator<<(float f); - wxTextCtrl& operator<<(double d); - wxTextCtrl& operator<<(const char c); - - virtual bool LoadFile(const wxString& file); - virtual bool SaveFile(const wxString& file); - virtual void WriteText(const wxString& text); - virtual void AppendText(const wxString& text); - virtual void DiscardEdits(); - virtual bool IsModified() const; - - virtual long XYToPosition(long x, long y) const ; - virtual void PositionToXY(long pos, long *x, long *y) const ; - virtual void ShowPosition(long pos); - virtual void Clear(); - - // callbacks - // --------- - void OnDropFiles(wxDropFilesEvent& event); -// void OnChar(wxKeyEvent& event); // Process 'enter' if required -// void OnEraseBackground(wxEraseEvent& event); - void OnCut(wxCommandEvent& event); - void OnCopy(wxCommandEvent& event); - void OnPaste(wxCommandEvent& event); - void OnUndo(wxCommandEvent& event); - void OnRedo(wxCommandEvent& event); - - void OnUpdateCut(wxUpdateUIEvent& event); - void OnUpdateCopy(wxUpdateUIEvent& event); - void OnUpdatePaste(wxUpdateUIEvent& event); - void OnUpdateUndo(wxUpdateUIEvent& event); - void OnUpdateRedo(wxUpdateUIEvent& event); - - // Implementation - // -------------- - virtual void Command(wxCommandEvent& event); + virtual wxSize DoGetBestSize(); -protected: - wxString m_fileName; - - DECLARE_EVENT_TABLE() +private: + DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxTextCtrl) }; #endif diff --git a/include/wx/os2/timer.h b/include/wx/os2/timer.h index d24372425a..975e76499b 100644 --- a/include/wx/os2/timer.h +++ b/include/wx/os2/timer.h @@ -1,25 +1,23 @@ ///////////////////////////////////////////////////////////////////////////// // Name: timer.h // Purpose: wxTimer class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_TIMER_H_ #define _WX_TIMER_H_ -#ifdef __GNUG__ -#pragma interface "timer.h" -#endif - #include "wx/object.h" class WXDLLEXPORT wxTimer: public wxObject { +friend void wxProcessTimer(wxTimer& timer); + public: wxTimer(); ~wxTimer(); @@ -31,32 +29,19 @@ public: virtual void Notify() = 0; // Override this member // Returns the current interval time (0 if stop) - int Interval() const { return m_milli; }; - bool OneShot() const { return m_oneShot; } + int Interval() const { return milli; }; + bool OneShot() const { return oneShot; } protected: - bool m_oneShot ; - int m_milli ; - int m_lastMilli ; + bool oneShot ; + int milli ; + int lastMilli ; - long m_id; + long id; private: DECLARE_ABSTRACT_CLASS(wxTimer) }; -/* Note: these are implemented in common/timercmn.cpp, so need to implement them separately. - * But you may need to modify timercmn.cpp. - */ - -// Timer functions (milliseconds) -void WXDLLEXPORT wxStartTimer(); - -// EXPERIMENTAL: comment this out if it doesn't compile. -bool WXDLLEXPORT wxGetLocalTime(long *timeZone, int *dstObserved); - -// Get number of seconds since 00:00:00 GMT, Jan 1st 1970. -long WXDLLEXPORT wxGetCurrentTime(); - #endif // _WX_TIMER_H_ diff --git a/include/wx/os2/toolbar.h b/include/wx/os2/toolbar.h index e9fa1e679a..9b1eff8e72 100644 --- a/include/wx/os2/toolbar.h +++ b/include/wx/os2/toolbar.h @@ -1,24 +1,21 @@ ///////////////////////////////////////////////////////////////////////////// // Name: toolbar.h // Purpose: wxToolBar class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/98 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_TOOLBAR_H_ #define _WX_TOOLBAR_H_ -#ifdef __GNUG__ -#pragma interface "toolbar.h" -#endif - +#if wxUSE_TOOLBAR #include "wx/tbarbase.h" -WXDLLEXPORT_DATA(extern const char*) wxToolBarNameStr; +WXDLLEXPORT_DATA(extern const wxChar*) wxToolBarNameStr; class WXDLLEXPORT wxToolBar: public wxToolBarBase { @@ -42,6 +39,9 @@ class WXDLLEXPORT wxToolBar: public wxToolBarBase long style = wxNO_BORDER|wxTB_HORIZONTAL, const wxString& name = wxToolBarNameStr); + // Call default behaviour + void OnMouseEvent(wxMouseEvent& event); + // If pushedBitmap is NULL, a reversed version of bitmap is // created and used as the pushed/toggled image. // If toggle is TRUE, the button toggles between the two states. @@ -60,18 +60,30 @@ class WXDLLEXPORT wxToolBar: public wxToolBarBase wxSize GetMaxSize() const; + virtual bool GetToolState(int toolIndex) const; + // Add all the buttons virtual bool CreateTools(); - virtual bool Layout() { return TRUE; } + virtual void SetRows(int nRows); + virtual void LayoutButtons() {} - // The post-tool-addition call. TODO: do here whatever's - // necessary for completing the toolbar construction. + // The post-tool-addition call bool Realize() { return CreateTools(); }; + // IMPLEMENTATION + virtual bool OS2Command(WXUINT param, WXWORD id); + virtual bool OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result); + + // Responds to colour changes + void OnSysColourChanged(wxSysColourChangedEvent& event); + protected: + WXHBITMAP m_hBitmap; DECLARE_EVENT_TABLE() }; +#endif // wxUSE_TOOLBAR + #endif // _WX_TOOLBAR_H_ diff --git a/include/wx/os2/tooltip.h b/include/wx/os2/tooltip.h index 8b7f805f1a..493225f84f 100644 --- a/include/wx/os2/tooltip.h +++ b/include/wx/os2/tooltip.h @@ -1,11 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// // Name: msw/tooltip.h // Purpose: wxToolTip class - tooltip control -// Author: Vadim Zeitlin +// Author: David Webster // Modified by: -// Created: 31.01.99 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) 1999 Robert Roebling, Vadim Zeitlin +// Copyright: (c) David Webster // Licence: wxWindows license /////////////////////////////////////////////////////////////////////////////// @@ -35,6 +35,7 @@ public: void RelayEvent(WXMSG *msg); private: + static WXHWND hwndTT; // create the tooltip ctrl for our parent frame if it doesn't exist yet // and return its window handle WXHWND GetToolTipCtrl(); diff --git a/include/wx/os2/treectrl.h b/include/wx/os2/treectrl.h index cb307ec0e9..03a386c715 100644 --- a/include/wx/os2/treectrl.h +++ b/include/wx/os2/treectrl.h @@ -1,295 +1,497 @@ ///////////////////////////////////////////////////////////////////////////// // Name: treectrl.h // Purpose: wxTreeCtrl class -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_TREECTRL_H_ #define _WX_TREECTRL_H_ -#ifdef __GNUG__ -#pragma interface "treectrl.h" -#endif - -#include "wx/control.h" -#include "wx/event.h" -#include "wx/imaglist.h" - -#define wxTREE_MASK_HANDLE 0x0001 -#define wxTREE_MASK_STATE 0x0002 -#define wxTREE_MASK_TEXT 0x0004 -#define wxTREE_MASK_IMAGE 0x0008 -#define wxTREE_MASK_SELECTED_IMAGE 0x0010 -#define wxTREE_MASK_CHILDREN 0x0020 -#define wxTREE_MASK_DATA 0x0040 - -#define wxTREE_STATE_BOLD 0x0001 -#define wxTREE_STATE_DROPHILITED 0x0002 -#define wxTREE_STATE_EXPANDED 0x0004 -#define wxTREE_STATE_EXPANDEDONCE 0x0008 -#define wxTREE_STATE_FOCUSED 0x0010 -#define wxTREE_STATE_SELECTED 0x0020 -#define wxTREE_STATE_CUT 0x0040 - -#define wxTREE_HITTEST_ABOVE 0x0001 // Above the client area. -#define wxTREE_HITTEST_BELOW 0x0002 // Below the client area. -#define wxTREE_HITTEST_NOWHERE 0x0004 // In the client area but below the last item. -#define wxTREE_HITTEST_ONITEMBUTTON 0x0010 // On the button associated with an item. -#define wxTREE_HITTEST_ONITEMICON 0x0020 // On the bitmap associated with an item. -#define wxTREE_HITTEST_ONITEMINDENT 0x0040 // In the indentation associated with an item. -#define wxTREE_HITTEST_ONITEMLABEL 0x0080 // On the label (string) associated with an item. -#define wxTREE_HITTEST_ONITEMRIGHT 0x0100 // In the area to the right of an item. -#define wxTREE_HITTEST_ONITEMSTATEICON 0x0200 // On the state icon for a tree view item that is in a user-defined state. -#define wxTREE_HITTEST_TOLEFT 0x0400 // To the right of the client area. -#define wxTREE_HITTEST_TORIGHT 0x0800 // To the left of the client area. - -#define wxTREE_HITTEST_ONITEM (wxTREE_HITTEST_ONITEMICON | wxTREE_HITTEST_ONITEMLABEL | wxTREE_HITTEST_ONITEMSTATEICON) - -// Flags for GetNextItem -enum { - wxTREE_NEXT_CARET, // Retrieves the currently selected item. - wxTREE_NEXT_CHILD, // Retrieves the first child item. The hItem parameter must be NULL. - wxTREE_NEXT_DROPHILITE, // Retrieves the item that is the target of a drag-and-drop operation. - wxTREE_NEXT_FIRSTVISIBLE, // Retrieves the first visible item. - wxTREE_NEXT_NEXT, // Retrieves the next sibling item. - wxTREE_NEXT_NEXTVISIBLE, // Retrieves the next visible item that follows the specified item. - wxTREE_NEXT_PARENT, // Retrieves the parent of the specified item. - wxTREE_NEXT_PREVIOUS, // Retrieves the previous sibling item. - wxTREE_NEXT_PREVIOUSVISIBLE, // Retrieves the first visible item that precedes the specified item. - wxTREE_NEXT_ROOT // Retrieves the first child item of the root item of which the specified item is a part. -}; - -// Flags for ExpandItem -enum { +#include "wx/textctrl.h" +#include "wx/dynarray.h" + +// the type for "untyped" data +typedef long wxDataType; + +// fwd decl +class WXDLLEXPORT wxImageList; +struct WXDLLEXPORT wxTreeViewItem; + +// a callback function used for sorting tree items, it should return -1 if the +// first item precedes the second, +1 if the second precedes the first or 0 if +// they're equivalent +class wxTreeItemData; + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- + +// values for the `flags' parameter of wxTreeCtrl::HitTest() which determine +// where exactly the specified point is situated: + // above the client area. +static const int wxTREE_HITTEST_ABOVE = 0x0001; + // below the client area. +static const int wxTREE_HITTEST_BELOW = 0x0002; + // in the client area but below the last item. +static const int wxTREE_HITTEST_NOWHERE = 0x0004; + // on the button associated with an item. +static const int wxTREE_HITTEST_ONITEMBUTTON = 0x0010; + // on the bitmap associated with an item. +static const int wxTREE_HITTEST_ONITEMICON = 0x0020; + // in the indentation associated with an item. +static const int wxTREE_HITTEST_ONITEMINDENT = 0x0040; + // on the label (string) associated with an item. +static const int wxTREE_HITTEST_ONITEMLABEL = 0x0080; + // in the area to the right of an item. +static const int wxTREE_HITTEST_ONITEMRIGHT = 0x0100; + // on the state icon for a tree view item that is in a user-defined state. +static const int wxTREE_HITTEST_ONITEMSTATEICON = 0x0200; + // to the right of the client area. +static const int wxTREE_HITTEST_TOLEFT = 0x0400; + // to the left of the client area. +static const int wxTREE_HITTEST_TORIGHT = 0x0800; + // anywhere on the item +static const int wxTREE_HITTEST_ONITEM = wxTREE_HITTEST_ONITEMICON | + wxTREE_HITTEST_ONITEMLABEL | + wxTREE_HITTEST_ONITEMSTATEICON; + +// NB: all the following flags are for compatbility only and will be removed in the +// next versions + +// flags for deprecated `Expand(int action)' +enum +{ wxTREE_EXPAND_EXPAND, wxTREE_EXPAND_COLLAPSE, wxTREE_EXPAND_COLLAPSE_RESET, wxTREE_EXPAND_TOGGLE }; -// Flags for InsertItem -enum { - wxTREE_INSERT_LAST = -1, - wxTREE_INSERT_FIRST = -2, - wxTREE_INSERT_SORT = -3 +// flags for deprecated InsertItem() variant +#define wxTREE_INSERT_FIRST 0xFFFF0001 +#define wxTREE_INSERT_LAST 0xFFFF0002 + +// ---------------------------------------------------------------------------- +// wxTreeItemId identifies an element of the tree. In this implementation, it's +// just a trivial wrapper around Win32 HTREEITEM. It's opaque for the +// application. +// ---------------------------------------------------------------------------- +class WXDLLEXPORT wxTreeItemId +{ +public: + // ctors + // 0 is invalid value for HTREEITEM + wxTreeItemId() { m_itemId = 0; } + + // default copy ctor/assignment operator are ok for us + + // accessors + // is this a valid tree item? + bool IsOk() const { return m_itemId != 0; } + + // conversion to/from either real (system-dependent) tree item id or + // to "long" which used to be the type for tree item ids in previous + // versions of wxWindows + + // for wxTreeCtrl usage only + wxTreeItemId(WXHTREEITEM itemId) { m_itemId = (long)itemId; } + operator WXHTREEITEM() const { return (WXHTREEITEM)m_itemId; } + + void operator=(WXHTREEITEM item) { m_itemId = (long) item; } + +protected: + long m_itemId; }; -class WXDLLEXPORT wxTreeItem: public wxObject +WX_DEFINE_EXPORTED_ARRAY(wxTreeItemId, wxArrayTreeItemIds); + +// ---------------------------------------------------------------------------- +// wxTreeItemData is some (arbitrary) user class associated with some item. The +// main advantage of having this class (compared to old untyped interface) is +// that wxTreeItemData's are destroyed automatically by the tree and, as this +// class has virtual dtor, it means that the memory will be automatically +// freed. OTOH, we don't just use wxObject instead of wxTreeItemData because +// the size of this class is critical: in any real application, each tree leaf +// will have wxTreeItemData associated with it and number of leaves may be +// quite big. +// +// Because the objects of this class are deleted by the tree, they should +// always be allocated on the heap! +// ---------------------------------------------------------------------------- +class WXDLLEXPORT wxTreeItemData : private wxTreeItemId { - DECLARE_DYNAMIC_CLASS(wxTreeItem) public: - long m_mask; - long m_itemId; - long m_state; - long m_stateMask; - wxString m_text; - int m_image; - int m_selectedImage; - int m_children; - long m_data; - - wxTreeItem(); - -// Accessors - inline long GetMask() const { return m_mask; } - inline long GetItemId() const { return m_itemId; } - inline long GetState() const { return m_state; } - inline long GetStateMask() const { return m_stateMask; } - inline wxString GetText() const { return m_text; } - inline int GetImage() const { return m_image; } - inline int GetSelectedImage() const { return m_selectedImage; } - inline int GetChildren() const { return m_children; } - inline long GetData() const { return m_data; } - - inline void SetMask(long mask) { m_mask = mask; } - inline void SetItemId(long id) { m_itemId = m_itemId = id; } - inline void SetState(long state) { m_state = state; } - inline void SetStateMask(long stateMask) { m_stateMask = stateMask; } - inline void GetText(const wxString& text) { m_text = text; } - inline void SetImage(int image) { m_image = image; } - inline void GetSelectedImage(int selImage) { m_selectedImage = selImage; } - inline void SetChildren(int children) { m_children = children; } - inline void SetData(long data) { m_data = data; } + // default ctor/copy ctor/assignment operator are ok + + // dtor is virtual and all the items are deleted by the tree control when + // it's deleted, so you normally don't have to care about freeing memory + // allocated in your wxTreeItemData-derived class + virtual ~wxTreeItemData() { } + + // accessors: set/get the item associated with this node + void SetId(const wxTreeItemId& id) { m_itemId = id; } + const wxTreeItemId GetId() const { return *this; } }; -class WXDLLEXPORT wxTreeCtrl: public wxControl +// ---------------------------------------------------------------------------- +// wxTreeCtrl +// ---------------------------------------------------------------------------- +class WXDLLEXPORT wxTreeCtrl : public wxControl { public: - /* - * Public interface - */ - // creation // -------- - wxTreeCtrl(); - - inline wxTreeCtrl(wxWindow *parent, wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT, - const wxValidator& validator = wxDefaultValidator, - const wxString& name = "wxTreeCtrl") + wxTreeCtrl() { Init(); } + + wxTreeCtrl(wxWindow *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT, + const wxValidator& validator = wxDefaultValidator, + const wxString& name = "wxTreeCtrl") { Create(parent, id, pos, size, style, validator, name); } - ~wxTreeCtrl(); - + + virtual ~wxTreeCtrl(); + bool Create(wxWindow *parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, - long style = wxTR_HAS_BUTTONS|wxTR_LINES_AT_ROOT, + long style = wxTR_HAS_BUTTONS | wxTR_LINES_AT_ROOT, const wxValidator& validator = wxDefaultValidator, const wxString& name = "wxTreeCtrl"); - + // accessors // --------- - // - int GetCount() const; - - // indent - int GetIndent() const; - void SetIndent(int indent); - // image list - wxImageList *GetImageList(int which = wxIMAGE_LIST_NORMAL) const; - void SetImageList(wxImageList *imageList, int which = wxIMAGE_LIST_NORMAL); - - // navigation inside the tree - long GetNextItem(long item, int code) const; - bool ItemHasChildren(long item) const; - long GetChild(long item) const; - long GetParent(long item) const; - long GetFirstVisibleItem() const; - long GetNextVisibleItem(long item) const; - long GetSelection() const; - long GetRootItem() const; - - // generic function for (g|s)etting item attributes - bool GetItem(wxTreeItem& info) const; - bool SetItem(wxTreeItem& info); - // item state - int GetItemState(long item, long stateMask) const; - bool SetItemState(long item, long state, long stateMask); - // item image - bool SetItemImage(long item, int image, int selImage); - // item text - wxString GetItemText(long item) const; - void SetItemText(long item, const wxString& str); - // custom data associated with the item - long GetItemData(long item) const; - bool SetItemData(long item, long data); - // convenience function - bool IsItemExpanded(long item) - { - return (GetItemState(item, wxTREE_STATE_EXPANDED) & - wxTREE_STATE_EXPANDED) != 0; - } - // bounding rect - bool GetItemRect(long item, wxRect& rect, bool textOnly = FALSE) const; - // - wxTextCtrl* GetEditControl() const; - + // get the total number of items in the control + size_t GetCount() const; + + // indent is the number of pixels the children are indented relative to + // the parents position. SetIndent() also redraws the control + // immediately. + unsigned int GetIndent() const; + void SetIndent(unsigned int indent); + + // spacing is the number of pixels between the start and the Text + // not implemented under wxMSW + unsigned int GetSpacing() const { return 18; } // return wxGTK default + void SetSpacing(unsigned int WXUNUSED(spacing)) { } + + // image list: these functions allow to associate an image list with + // the control and retrieve it. Note that the control does _not_ delete + // the associated image list when it's deleted in order to allow image + // lists to be shared between different controls. + // + // The normal image list is for the icons which correspond to the + // normal tree item state (whether it is selected or not). + // Additionally, the application might choose to show a state icon + // which corresponds to an app-defined item state (for example, + // checked/unchecked) which are taken from the state image list. + wxImageList *GetImageList() const; + wxImageList *GetStateImageList() const; + + void SetImageList(wxImageList *imageList); + void SetStateImageList(wxImageList *imageList); + + // Functions to work with tree ctrl items. Unfortunately, they can _not_ be + // member functions of wxTreeItem because they must know the tree the item + // belongs to for Windows implementation and storing the pointer to + // wxTreeCtrl in each wxTreeItem is just too much waste. + + // accessors + // --------- + + // retrieve items label + wxString GetItemText(const wxTreeItemId& item) const; + // get one of the images associated with the item (normal by default) + int GetItemImage(const wxTreeItemId& item, + wxTreeItemIcon which = wxTreeItemIcon_Normal) const; + // get the data associated with the item + wxTreeItemData *GetItemData(const wxTreeItemId& item) const; + + // modifiers + // --------- + + // set items label + void SetItemText(const wxTreeItemId& item, const wxString& text); + // get one of the images associated with the item (normal by default) + void SetItemImage(const wxTreeItemId& item, int image, + wxTreeItemIcon which = wxTreeItemIcon_Normal); + // associate some data with the item + void SetItemData(const wxTreeItemId& item, wxTreeItemData *data); + + // force appearance of [+] button near the item. This is useful to + // allow the user to expand the items which don't have any children now + // - but instead add them only when needed, thus minimizing memory + // usage and loading time. + void SetItemHasChildren(const wxTreeItemId& item, bool has = TRUE); + + // the item will be shown in bold + void SetItemBold(const wxTreeItemId& item, bool bold = TRUE); + + // the item will be shown with a drop highlight + void SetItemDropHighlight(const wxTreeItemId& item, bool highlight = TRUE); + + // item status inquiries + // --------------------- + + // is the item visible (it might be outside the view or not expanded)? + bool IsVisible(const wxTreeItemId& item) const; + // does the item has any children? + bool ItemHasChildren(const wxTreeItemId& item) const; + // is the item expanded (only makes sense if HasChildren())? + bool IsExpanded(const wxTreeItemId& item) const; + // is this item currently selected (the same as has focus)? + bool IsSelected(const wxTreeItemId& item) const; + // is item text in bold font? + bool IsBold(const wxTreeItemId& item) const; + + // number of children + // ------------------ + + // if 'recursively' is FALSE, only immediate children count, otherwise + // the returned number is the number of all items in this branch + size_t GetChildrenCount(const wxTreeItemId& item, + bool recursively = TRUE) const; + + // navigation + // ---------- + + // wxTreeItemId.IsOk() will return FALSE if there is no such item + + // get the root tree item + wxTreeItemId GetRootItem() const; + + // get the item currently selected (may return NULL if no selection) + wxTreeItemId GetSelection() const; + + // get the items currently selected, return the number of such item + // + // NB: this operation is expensive and can take a long time for a + // control with a lot of items (~ O(number of items)). + size_t GetSelections(wxArrayTreeItemIds& selections) const; + + // get the parent of this item (may return NULL if root) + wxTreeItemId GetParent(const wxTreeItemId& item) const; + + // for this enumeration function you must pass in a "cookie" parameter + // which is opaque for the application but is necessary for the library + // to make these functions reentrant (i.e. allow more than one + // enumeration on one and the same object simultaneously). Of course, + // the "cookie" passed to GetFirstChild() and GetNextChild() should be + // the same! + + // get the first child of this item + wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& _cookie) const; + // get the next child + wxTreeItemId GetNextChild(const wxTreeItemId& item, long& _cookie) const; + // get the last child of this item - this method doesn't use cookies + wxTreeItemId GetLastChild(const wxTreeItemId& item) const; + + // get the next sibling of this item + wxTreeItemId GetNextSibling(const wxTreeItemId& item) const; + // get the previous sibling + wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const; + + // get first visible item + wxTreeItemId GetFirstVisibleItem() const; + // get the next visible item: item must be visible itself! + // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem() + wxTreeItemId GetNextVisible(const wxTreeItemId& item) const; + // get the previous visible item: item must be visible itself! + wxTreeItemId GetPrevVisible(const wxTreeItemId& item) const; + // operations // ---------- - // adding/deleting items - bool DeleteItem(long item); - long InsertItem(long parent, wxTreeItem& info, - long insertAfter = wxTREE_INSERT_LAST); - // If image > -1 and selImage == -1, the same image is used for - // both selected and unselected items. - long InsertItem(long parent, const wxString& label, - int image = -1, int selImage = -1, - long insertAfter = wxTREE_INSERT_LAST); - - // changing item state - bool ExpandItem(long item) { return ExpandItem(item, wxTREE_EXPAND_EXPAND); } - bool CollapseItem(long item) { return ExpandItem(item, wxTREE_EXPAND_COLLAPSE); } - bool ToggleItem(long item) { return ExpandItem(item, wxTREE_EXPAND_TOGGLE); } - // common interface for {Expand|Collapse|Toggle}Item - bool ExpandItem(long item, int action); - - // - bool SelectItem(long item); - bool ScrollTo(long item); - bool DeleteAllItems(); - - // Edit the label (tree must have the focus) - wxTextCtrl* EditLabel(long item, wxClassInfo* textControlClass = CLASSINFO(wxTextCtrl)); - - // End label editing, optionally cancelling the edit - bool EndEditLabel(bool cancel); - - long HitTest(const wxPoint& point, int& flags); - // wxImageList *CreateDragImage(long item); - bool SortChildren(long item); - bool EnsureVisible(long item); - - void Command(wxCommandEvent& event) { ProcessCommand(event); }; + + // add the root node to the tree + wxTreeItemId AddRoot(const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item in as the first child of the parent + wxTreeItemId PrependItem(const wxTreeItemId& parent, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item after a given one + wxTreeItemId InsertItem(const wxTreeItemId& parent, + const wxTreeItemId& idPrevious, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item in as the last child of the parent + wxTreeItemId AppendItem(const wxTreeItemId& parent, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // delete this item and associated data if any + void Delete(const wxTreeItemId& item); + // delete all children (but don't delete the item itself) + // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events + void DeleteChildren(const wxTreeItemId& item); + // delete all items from the tree + // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events + void DeleteAllItems(); + + // expand this item + void Expand(const wxTreeItemId& item); + // collapse the item without removing its children + void Collapse(const wxTreeItemId& item); + // collapse the item and remove all children + void CollapseAndReset(const wxTreeItemId& item); + // toggles the current state + void Toggle(const wxTreeItemId& item); + + // remove the selection from currently selected item (if any) + void Unselect(); + // unselect all items (only makes sense for multiple selection control) + void UnselectAll(); + // select this item + void SelectItem(const wxTreeItemId& item); + // make sure this item is visible (expanding the parent item and/or + // scrolling to this item if necessary) + void EnsureVisible(const wxTreeItemId& item); + // scroll to this item (but don't expand its parent) + void ScrollTo(const wxTreeItemId& item); + + // start editing the item label: this (temporarily) replaces the item + // with a one line edit control. The item will be selected if it hadn't + // been before. textCtrlClass parameter allows you to create an edit + // control of arbitrary user-defined class deriving from wxTextCtrl. + wxTextCtrl* EditLabel(const wxTreeItemId& item, + wxClassInfo* textCtrlClass = CLASSINFO(wxTextCtrl)); + // returns the same pointer as StartEdit() if the item is being edited, + // NULL otherwise (it's assumed that no more than one item may be + // edited simultaneously) + wxTextCtrl* GetEditControl() const; + // end editing and accept or discard the changes to item label + void EndEditLabel(const wxTreeItemId& item, bool discardChanges = FALSE); + + // sorting + // this function is called to compare 2 items and should return -1, 0 + // or +1 if the first item is less than, equal to or greater than the + // second one. The base class version performs alphabetic comparaison + // of item labels (GetText) + virtual int OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2); + // sort the children of this item using OnCompareItems + // + // NB: this function is not reentrant and not MT-safe (FIXME)! + void SortChildren(const wxTreeItemId& item); + + // helpers + // ------- + + // determine to which item (if any) belongs the given point (the + // coordinates specified are relative to the client area of tree ctrl) + // and fill the flags parameter with a bitmask of wxTREE_HITTEST_xxx + // constants. + // + // The first function is more portable (because easier to implement + // on other platforms), but the second one returns some extra info. + wxTreeItemId HitTest(const wxPoint& point) + { int dummy; return HitTest(point, dummy); } + wxTreeItemId HitTest(const wxPoint& point, int& flags); + + // get the bounding rectangle of the item (or of its label only) + bool GetBoundingRect(const wxTreeItemId& item, + wxRect& rect, + bool textOnly = FALSE) const; + + // deprecated + // ---------- + + // these methods are deprecated and will be removed in future versions of + // wxWindows, they're here for compatibility only, don't use them in new + // code (the comments indicate why these methods are now useless and how to + // replace them) + + // use Expand, Collapse, CollapseAndReset or Toggle + void ExpandItem(const wxTreeItemId& item, int action); + + // use AddRoot, PrependItem or AppendItem + wxTreeItemId InsertItem(const wxTreeItemId& parent, + const wxString& text, + int image = -1, int selImage = -1, + long insertAfter = wxTREE_INSERT_LAST); + + // use Set/GetImageList and Set/GetStateImageList + wxImageList *GetImageList(int) const + { return GetImageList(); } + void SetImageList(wxImageList *imageList, int) + { SetImageList(imageList); } + + // use Set/GetItemImage directly + // get the selected item image + int GetItemSelectedImage(const wxTreeItemId& item) const + { return GetItemImage(item, wxTreeItemIcon_Selected); } + // set the selected item image + void SetItemSelectedImage(const wxTreeItemId& item, int image) + { SetItemImage(item, image, wxTreeItemIcon_Selected); } + + // implementation + // -------------- + virtual bool OS2Command(WXUINT param, WXWORD id); + virtual bool OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result); + + // get/set the check state for the item (only for wxTR_MULTIPLE) + bool IsItemChecked(const wxTreeItemId& item) const; + void SetItemCheck(const wxTreeItemId& item, bool check = TRUE); protected: - wxTextCtrl* m_textCtrl; - wxImageList* m_imageListNormal; - wxImageList* m_imageListState; + // SetImageList helper + void SetAnyImageList(wxImageList *imageList, int which); - DECLARE_DYNAMIC_CLASS(wxTreeCtrl) -}; + wxTextCtrl *m_textCtrl; // used while editing the item label + wxImageList *m_imageListNormal, // images for tree elements + *m_imageListState; // special images for app defined states -/* - wxEVT_COMMAND_TREE_BEGIN_DRAG, - wxEVT_COMMAND_TREE_BEGIN_RDRAG, - wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, - wxEVT_COMMAND_TREE_END_LABEL_EDIT, - wxEVT_COMMAND_TREE_DELETE_ITEM, - wxEVT_COMMAND_TREE_GET_INFO, - wxEVT_COMMAND_TREE_SET_INFO, - wxEVT_COMMAND_TREE_ITEM_EXPANDED, - wxEVT_COMMAND_TREE_ITEM_EXPANDING, - wxEVT_COMMAND_TREE_ITEM_COLLAPSED, - wxEVT_COMMAND_TREE_ITEM_COLLAPSING, - wxEVT_COMMAND_TREE_SEL_CHANGED, - wxEVT_COMMAND_TREE_SEL_CHANGING, - wxEVT_COMMAND_TREE_KEY_DOWN -*/ - -class WXDLLEXPORT wxTreeEvent: public wxCommandEvent -{ - DECLARE_DYNAMIC_CLASS(wxTreeEvent) +private: + // the common part of all ctors + void Init(); - public: - wxTreeEvent(wxEventType commandType = wxEVT_NULL, int id = 0); + // helper functions + inline bool DoGetItem(wxTreeViewItem *tvItem) const; + inline void DoSetItem(wxTreeViewItem *tvItem); - int m_code; - wxTreeItem m_item; - long m_oldItem; - wxPoint m_pointDrag; + inline void DoExpand(const wxTreeItemId& item, int flag); - inline long GetOldItem() const { return m_oldItem; } - inline wxTreeItem& GetItem() const { return (wxTreeItem&) m_item; } - inline wxPoint GetPoint() const { return m_pointDrag; } - inline int GetCode() const { return m_code; } -}; + wxTreeItemId DoInsertItem(const wxTreeItemId& parent, + wxTreeItemId hInsertAfter, + const wxString& text, + int image, int selectedImage, + wxTreeItemData *data); + + int DoGetItemImageFromData(const wxTreeItemId& item, + wxTreeItemIcon which) const; + void DoSetItemImageFromData(const wxTreeItemId& item, + int image, + wxTreeItemIcon which) const; + void DoSetItemImages(const wxTreeItemId& item, int image, int imageSel); -typedef void (wxEvtHandler::*wxTreeEventFunction)(wxTreeEvent&); - -#define EVT_TREE_BEGIN_DRAG(id, fn) { wxEVT_COMMAND_TREE_BEGIN_DRAG, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_BEGIN_RDRAG(id, fn) { wxEVT_COMMAND_TREE_BEGIN_RDRAG, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_BEGIN_LABEL_EDIT(id, fn) { wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_END_LABEL_EDIT(id, fn) { wxEVT_COMMAND_TREE_END_LABEL_EDIT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_DELETE_ITEM(id, fn) { wxEVT_COMMAND_TREE_DELETE_ITEM, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_GET_INFO(id, fn) { wxEVT_COMMAND_TREE_GET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_SET_INFO(id, fn) { wxEVT_COMMAND_TREE_SET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_ITEM_EXPANDED(id, fn) { wxEVT_COMMAND_TREE_ITEM_EXPANDED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_ITEM_EXPANDING(id, fn) { wxEVT_COMMAND_TREE_ITEM_EXPANDING, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_ITEM_COLLAPSED(id, fn) { wxEVT_COMMAND_TREE_ITEM_COLLAPSED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_ITEM_COLLAPSING(id, fn) { wxEVT_COMMAND_TREE_ITEM_COLLAPSING, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_SEL_CHANGED(id, fn) { wxEVT_COMMAND_TREE_SEL_CHANGED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_SEL_CHANGING(id, fn) { wxEVT_COMMAND_TREE_SEL_CHANGING, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -#define EVT_TREE_KEY_DOWN(id, fn) { wxEVT_COMMAND_TREE_KEY_DOWN, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, + void DeleteTextCtrl(); + + // support for additional item images + friend class wxTreeItemIndirectData; + void SetIndirectItemData(const wxTreeItemId& item, + wxTreeItemIndirectData *data); + bool HasIndirectData(const wxTreeItemId& item) const; + + wxArrayTreeItemIds m_itemsWithIndirectData; + + DECLARE_DYNAMIC_CLASS(wxTreeCtrl) +}; #endif // _WX_TREECTRL_H_ diff --git a/include/wx/os2/wave.h b/include/wx/os2/wave.h index e55bd5aa5f..fdfce64dc7 100644 --- a/include/wx/os2/wave.h +++ b/include/wx/os2/wave.h @@ -2,21 +2,17 @@ // Name: wave.h // Purpose: wxWave class (loads and plays short Windows .wav files). // Optional on non-Windows platforms. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_WAVE_H_ #define _WX_WAVE_H_ -#ifdef __GNUG__ -#pragma interface "wave.h" -#endif - #include "wx/object.h" class wxWave : public wxObject @@ -24,10 +20,15 @@ class wxWave : public wxObject public: wxWave(); wxWave(const wxString& fileName, bool isResource = FALSE); + wxWave(int size, const wxByte* data); ~wxWave(); public: + // Create from resource or file bool Create(const wxString& fileName, bool isResource = FALSE); + // Create from data + bool Create(int size, const wxByte* data); + bool IsOk() const { return (m_waveData ? TRUE : FALSE); }; bool Play(bool async = TRUE, bool looped = FALSE) const; @@ -35,7 +36,7 @@ protected: bool Free(); private: - char* m_waveData; + wxByte* m_waveData; int m_waveLength; bool m_isResource; }; diff --git a/include/wx/treectrl.h b/include/wx/treectrl.h index cacdbe2dc3..33dbe7a126 100644 --- a/include/wx/treectrl.h +++ b/include/wx/treectrl.h @@ -48,7 +48,7 @@ enum wxTreeItemIcon #elif defined(__WXMAC__) #include "wx/generic/treectrl.h" #elif defined(__WXPM__) - #include "wx/generic/treectrl.h" + #include "wx/os2/treectrl.h" #elif defined(__WXSTUBS__) #include "wx/generic/treectrl.h" #endif @@ -119,7 +119,7 @@ typedef void (wxEvtHandler::*wxTreeEventFunction)(wxTreeEvent&); #define EVT_TREE_GET_INFO(id, fn) { wxEVT_COMMAND_TREE_GET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, #define EVT_TREE_SET_INFO(id, fn) { wxEVT_COMMAND_TREE_SET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, -// GetItem() is the item being expanded/collapsed, the "ING" versions can use +// GetItem() is the item being expanded/collapsed, the "ING" versions can use #define EVT_TREE_ITEM_EXPANDED(id, fn) { wxEVT_COMMAND_TREE_ITEM_EXPANDED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, #define EVT_TREE_ITEM_EXPANDING(id, fn) { wxEVT_COMMAND_TREE_ITEM_EXPANDING, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, #define EVT_TREE_ITEM_COLLAPSED(id, fn) { wxEVT_COMMAND_TREE_ITEM_COLLAPSED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxTreeEventFunction) & fn, (wxObject *) NULL }, diff --git a/src/os2/makefile.va b/src/os2/makefile.va index 144f3dc781..9f9526ac33 100644 --- a/src/os2/makefile.va +++ b/src/os2/makefile.va @@ -351,6 +351,19 @@ OS2OBJS = \ ..\os2\$D\spinctrl.obj \ ..\os2\$D\statbmp.obj \ ..\os2\$D\statbox.obj \ + ..\os2\$D\stattext.obj \ + ..\os2\$D\statbrpm.obj \ + ..\os2\$D\tabctrl.obj \ + ..\os2\$D\taskbar.obj \ + ..\os2\$D\textctrl.obj \ + ..\os2\$D\thread.obj \ + ..\os2\$D\timer.obj \ + ..\os2\$D\toolbar.obj \ + ..\os2\$D\tooltip.obj \ + ..\os2\$D\treectrl.obj \ + ..\os2\$D\utils.obj \ + ..\os2\$D\utilsexc.obj \ + ..\os2\$D\wave.obj \ ..\os2\$D\window.obj OS2LIBOBJS1 = \ @@ -417,6 +430,19 @@ OS2LIBOBJS2 = \ spinctrl.obj \ statbmp.obj \ statbox.obj \ + stattext.obj \ + statbrpm.obj \ + tabctrl.obj \ + taskbar.obj \ + textctrl.obj \ + thread.obj \ + timer.obj \ + toolbar.obj \ + tooltip.obj \ + treectrl.obj \ + utils.obj \ + utilsexc.obj \ + wave.obj \ window.obj HTMLOBJS = \ @@ -627,6 +653,19 @@ $(OS2LIBOBJS2): copy ..\os2\$D\spinctrl.obj copy ..\os2\$D\statbmp.obj copy ..\os2\$D\statbox.obj + copy ..\os2\$D\stattext.obj + copy ..\os2\$D\statbrpm.obj + copy ..\os2\$D\tabctrl.obj + copy ..\os2\$D\taskbar.obj + copy ..\os2\$D\textctrl.obj + copy ..\os2\$D\thread.obj + copy ..\os2\$D\timer.obj + copy ..\os2\$D\toolbar.obj + copy ..\os2\$D\tooltip.obj + copy ..\os2\$D\treectrl.obj + copy ..\os2\$D\utils.obj + copy ..\os2\$D\utilsexc.obj + copy ..\os2\$D\wave.obj copy ..\os2\$D\window.obj # wxWindows library as DLL diff --git a/src/os2/statbrpm.cpp b/src/os2/statbrpm.cpp new file mode 100644 index 0000000000..8f6b10a39c --- /dev/null +++ b/src/os2/statbrpm.cpp @@ -0,0 +1,171 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: statbar.cpp +// Purpose: native implementation of wxStatusBar (optional) +// Author: David Webster +// Modified by: +// Created: 10/17/99 +// RCS-ID: $Id$ +// Copyright: (c) David Webster +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// 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/settings.h" + #include "wx/dcclient.h" +#endif + +#include "wx/log.h" +#include "wx/generic/statusbr.h" +#include "wx/os2/statusbr.h" + +#include "wx/os2/private.h" + +#if !USE_SHARED_LIBRARY +IMPLEMENT_DYNAMIC_CLASS(wxStatusBarPM, wxStatusBar); + +BEGIN_EVENT_TABLE(wxStatusBarPM, wxStatusBar) + EVT_SIZE(wxStatusBarPM::OnSize) +END_EVENT_TABLE() +#endif //USE_SHARED_LIBRARY + + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxStatusBarPM class +// ---------------------------------------------------------------------------- + +wxStatusBarPM::wxStatusBarPM() +{ + SetParent(NULL); + m_hWnd = 0; + m_windowId = 0; +} + +wxStatusBarPM::wxStatusBarPM(wxWindow *parent, wxWindowID id, long style) +{ + Create(parent, id, style); +} + +bool wxStatusBarPM::Create(wxWindow *parent, wxWindowID id, long style) +{ + SetParent(parent); + + if (id == -1) + m_windowId = NewControlId(); + else + m_windowId = id; + + // TODO: create status bar + return FALSE; +} + +void wxStatusBarPM::CopyFieldsWidth(const int widths[]) +{ + if (widths && !m_statusWidths) + m_statusWidths = new int[m_nFields]; + + if ( widths != NULL ) { + for ( int i = 0; i < m_nFields; i++ ) + m_statusWidths[i] = widths[i]; + } + else { + delete [] m_statusWidths; + m_statusWidths = NULL; + } +} + +void wxStatusBarPM::SetFieldsCount(int nFields, const int widths[]) +{ + wxASSERT( (nFields > 0) && (nFields < 255) ); + + m_nFields = nFields; + + CopyFieldsWidth(widths); + SetFieldsWidth(); +} + +void wxStatusBarPM::SetStatusWidths(int n, const int widths[]) +{ + wxASSERT( n == m_nFields ); + + CopyFieldsWidth(widths); + SetFieldsWidth(); +} + +void wxStatusBarPM::SetFieldsWidth() +{ + int *pWidths = new int[m_nFields]; + + int nWindowWidth, y; + GetClientSize(&nWindowWidth, &y); + + if ( m_statusWidths == NULL ) { + // default: all fields have the same width + int nWidth = nWindowWidth / m_nFields; + for ( int i = 0; i < m_nFields; i++ ) + pWidths[i] = (i + 1) * nWidth; + } + else { + // -1 doesn't mean the same thing for wxWindows and Win32, recalc + int nTotalWidth = 0, + nVarCount = 0, + i; + for ( i = 0; i < m_nFields; i++ ) { + if ( m_statusWidths[i] == -1 ) + nVarCount++; + else + nTotalWidth += m_statusWidths[i]; + } + + if ( nVarCount == 0 ) { + // wrong! at least one field must be of variable width + wxFAIL; + + nVarCount++; + } + + int nVarWidth = (nWindowWidth - nTotalWidth) / nVarCount; + + // do fill the array + int nCurPos = 0; + for ( i = 0; i < m_nFields; i++ ) { + if ( m_statusWidths[i] == -1 ) + nCurPos += nVarWidth; + else + nCurPos += m_statusWidths[i]; + pWidths[i] = nCurPos; + } + } + + // TODO: set widths + + delete [] pWidths; +} + +void wxStatusBarPM::SetStatusText(const wxString& strText, int nField) +{ + // TODO +} + +wxString wxStatusBarPM::GetStatusText(int nField) const +{ + wxASSERT( (nField > -1) && (nField < m_nFields) ); + + // TODO + return wxString(""); +} + +void wxStatusBarPM::OnSize(wxSizeEvent& event) +{ + // adjust fields widths to the new size + SetFieldsWidth(); +} + diff --git a/src/os2/stattext.cpp b/src/os2/stattext.cpp index 3b19c7184d..91b15ada8f 100644 --- a/src/os2/stattext.cpp +++ b/src/os2/stattext.cpp @@ -1,21 +1,25 @@ ///////////////////////////////////////////////////////////////////////////// // Name: stattext.cpp // Purpose: wxStaticText -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: 04/01/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "stattext.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" +#ifndef WX_PRECOMP +#include "wx/event.h" #include "wx/app.h" -#include "wx/stattext.h" +#include "wx/brush.h" +#endif +#include "wx/stattext.h" +#include "wx/os2/private.h" #include #if !USE_SHARED_LIBRARY @@ -29,32 +33,105 @@ bool wxStaticText::Create(wxWindow *parent, wxWindowID id, long style, const wxString& name) { - SetName(name); - if (parent) parent->AddChild(this); + SetName(name); + if (parent) parent->AddChild(this); + + SetBackgroundColour(parent->GetBackgroundColour()) ; + SetForegroundColour(parent->GetForegroundColour()) ; - SetBackgroundColour(parent->GetBackgroundColour()) ; - SetForegroundColour(parent->GetForegroundColour()) ; + if ( id == -1 ) + m_windowId = (int)NewControlId(); + else + m_windowId = id; - if ( id == -1 ) - m_windowId = (int)NewControlId(); - else - m_windowId = id; + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; - m_windowStyle = style; + m_windowStyle = style; - SetFont(parent->GetFont()); + // TODO + SubclassWin(m_hWnd); - // TODO - return FALSE; + SetFont(parent->GetFont()); + SetSize(x, y, width, height); + + return FALSE; } -void wxStaticText::SetSize(int x, int y, int width, int height, int sizeFlags) +wxSize wxStaticText::DoGetBestSize() { - // TODO + wxString text(wxGetWindowText(GetHWND())); + + int widthTextMax = 0, widthLine, + heightTextTotal = 0, heightLine; + + wxString curLine; + for ( const wxChar *pc = text; ; pc++ ) { + if ( *pc == wxT('\n') || *pc == wxT('\0') ) { + GetTextExtent(curLine, &widthLine, &heightLine); + if ( widthLine > widthTextMax ) + widthTextMax = widthLine; + heightTextTotal += heightLine; + + if ( *pc == wxT('\n') ) { + curLine.Empty(); + } + else { + // the end of string + break; + } + } + else { + curLine += *pc; + } + } + + return wxSize(widthTextMax, heightTextTotal); } void wxStaticText::SetLabel(const wxString& label) { // TODO + + // adjust the size of the window to fit to the label (this behaviour is + // backward compatible and generally makes sense but we might want to still + // provide the user a way to disable it) (VZ) + DoSetSize(-1, -1, -1, -1, wxSIZE_AUTO_WIDTH | wxSIZE_AUTO_HEIGHT); +} + +WXHBRUSH wxStaticText::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, + WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +{ + // TODO: +/* + if (GetParent()->GetTransparentBackground()) + SetBkMode((HDC) pDC, TRANSPARENT); + else + SetBkMode((HDC) pDC, OPAQUE); + + ::SetBkColor((HDC) pDC, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue())); + ::SetTextColor((HDC) pDC, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue())); + + wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID); + // Note that this will be cleaned up in wxApp::OnIdle, if backgroundBrush + // has a zero usage count. +// backgroundBrush->RealizeResource(); + return (WXHBRUSH) backgroundBrush->GetResourceHandle(); +*/ + return (WXHBRUSH)0; +} + +MRESULT wxStaticText::OS2WindowProc(HWND hwnd, WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +{ + // Ensure that static items get messages. Some controls don't like this + // message to be intercepted (e.g. RichEdit), hence the tests. +// TODO: +/* + if (nMsg == WM_NCHITTEST) + return (long)HTCLIENT; +*/ + return wxWindow::OS2WindowProc(hwnd, nMsg, wParam, lParam); } diff --git a/src/os2/statusbr.cpp b/src/os2/statusbr.cpp index dff1ddec34..e69de29bb2 100644 --- a/src/os2/statusbr.cpp +++ b/src/os2/statusbr.cpp @@ -1,162 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// Name: statbar.cpp -// Purpose: native implementation of wxStatusBar (optional) -// Author: AUTHOR -// Modified by: -// Created: ??/??/98 -// RCS-ID: $Id$ -// Copyright: (c) 1998 AUTHOR -// Licence: wxWindows licence -/////////////////////////////////////////////////////////////////////////////// - -#ifdef __GNUG__ -#pragma implementation "statusbr.h" -#endif - -// ---------------------------------------------------------------------------- -// headers -// ---------------------------------------------------------------------------- - -#include "wx/stubs/statusbr.h" - -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxStatusBarXX, wxStatusBar); - -BEGIN_EVENT_TABLE(wxStatusBarXX, wxStatusBar) - EVT_SIZE(wxStatusBarXX::OnSize) -END_EVENT_TABLE() -#endif //USE_SHARED_LIBRARY - - -// ============================================================================ -// implementation -// ============================================================================ - -// ---------------------------------------------------------------------------- -// wxStatusBarXX class -// ---------------------------------------------------------------------------- - -wxStatusBarXX::wxStatusBarXX() -{ - SetParent(NULL); -} - -wxStatusBarXX::wxStatusBarXX(wxWindow *parent, wxWindowID id, long style) -{ - Create(parent, id, style); -} - -bool wxStatusBarXX::Create(wxWindow *parent, wxWindowID id, long style) -{ - SetParent(parent); - - if (id == -1) - m_windowId = NewControlId(); - else - m_windowId = id; - - // TODO: create status bar - return FALSE; -} - -void wxStatusBarXX::SetFieldsCount(int nFields, const int widths[]) -{ - wxASSERT( (nFields > 0) && (nFields < 255) ); - - m_nFields = nFields; - - CopyFieldsWidth(widths); - SetFieldsWidth(); -} - -void wxStatusBarXX::SetStatusWidths(int n, const int widths[]) -{ - wxASSERT( n == m_nFields ); - - CopyFieldsWidth(widths); - SetFieldsWidth(); -} - -void wxStatusBarXX::CopyFieldsWidth(const int widths[]) -{ - if (widths && !m_statusWidths) - m_statusWidths = new int[m_nFields]; - - if ( widths != NULL ) { - for ( int i = 0; i < m_nFields; i++ ) - m_statusWidths[i] = widths[i]; - } - else { - delete [] m_statusWidths; - m_statusWidths = NULL; - } -} - -void wxStatusBarXX::SetFieldsWidth() -{ - int *pWidths = new int[m_nFields]; - - int nWindowWidth, y; - GetClientSize(&nWindowWidth, &y); - - if ( m_statusWidths == NULL ) { - // default: all fields have the same width - int nWidth = nWindowWidth / m_nFields; - for ( int i = 0; i < m_nFields; i++ ) - pWidths[i] = (i + 1) * nWidth; - } - else { - // -1 doesn't mean the same thing for wxWindows and Win32, recalc - int nTotalWidth = 0, - nVarCount = 0, - i; - for ( i = 0; i < m_nFields; i++ ) { - if ( m_statusWidths[i] == -1 ) - nVarCount++; - else - nTotalWidth += m_statusWidths[i]; - } - - if ( nVarCount == 0 ) { - // wrong! at least one field must be of variable width - wxFAIL; - - nVarCount++; - } - - int nVarWidth = (nWindowWidth - nTotalWidth) / nVarCount; - - // do fill the array - int nCurPos = 0; - for ( i = 0; i < m_nFields; i++ ) { - if ( m_statusWidths[i] == -1 ) - nCurPos += nVarWidth; - else - nCurPos += m_statusWidths[i]; - pWidths[i] = nCurPos; - } - } - - // TODO: set widths - - delete [] pWidths; -} - -void wxStatusBarXX::SetStatusText(const wxString& strText, int nField) -{ - // TODO -} - -wxString wxStatusBarXX::GetStatusText(int nField) const -{ - wxASSERT( (nField > -1) && (nField < m_nFields) ); - - // TODO - return wxString(""); -} - -void wxStatusBarXX::OnSize(wxSizeEvent& event) -{ - // adjust fields widths to the new size - SetFieldsWidth(); -} diff --git a/src/os2/tabctrl.cpp b/src/os2/tabctrl.cpp index b3b45a72d1..677ee8a69c 100644 --- a/src/os2/tabctrl.cpp +++ b/src/os2/tabctrl.cpp @@ -1,20 +1,31 @@ ///////////////////////////////////////////////////////////////////////////// // Name: tabctrl.cpp // Purpose: wxTabCtrl -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "tabctrl.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include "wx/wx.h" #endif -#include "wx/control.h" -#include "wx/tabctrl.h" +#include "malloc.h" + +#define INCL_PM +#include + +//#include "wx/msw/dib.h" +#include "wx/os2/tabctrl.h" +#include "wx/app.h" +#include "wx/os2/private.h" +#include "wx/os2/imaglist.h" #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxTabCtrl, wxControl) @@ -33,28 +44,106 @@ bool wxTabCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, cons { m_imageList = NULL; + m_backgroundColour = *wxWHITE; // TODO: wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), +// GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE))); + m_foregroundColour = *wxBLACK ; + SetName(name); + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; + m_windowStyle = style; + SetFont(* (wxTheFontList->FindOrCreateFont(11, wxSWISS, wxNORMAL, wxNORMAL))); + SetParent(parent); + DWORD msflags = 0; + + if (width <= 0) + width = 100; + if (height <= 0) + height = 30; + if (x < 0) + x = 0; + if (y < 0) + y = 0; + m_windowId = (id < 0 ? NewControlId() : id); - if (parent) parent->AddChild(this); + long tabStyle = 0; + // Create the toolbar control. + HWND hWndTabCtrl = 0; // TODO: create tab control + + m_hWnd = (WXHWND) hWndTabCtrl; + if (parent) parent->AddChild(this); + + SubclassWin((WXHWND) hWndTabCtrl); + return FALSE; } wxTabCtrl::~wxTabCtrl() { + UnsubclassWin(); } -void wxTabCtrl::Command(wxCommandEvent& event) +bool wxTabCtrl::OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { + wxTabEvent event(wxEVT_NULL, m_windowId); + wxEventType eventType = wxEVT_NULL; +// TODO: +/* + NMHDR* hdr1 = (NMHDR*) lParam; + switch ( hdr1->code ) + { + case TCN_SELCHANGE: + eventType = wxEVT_COMMAND_TAB_SEL_CHANGED; + break; + + case TCN_SELCHANGING: + eventType = wxEVT_COMMAND_TAB_SEL_CHANGING; + break; + + case TTN_NEEDTEXT: + { + // TODO +// if (tool->m_shortHelpString != "") +// ttText->lpszText = (char *) (const char *)tool->m_shortHelpString; + } + + default : + return wxControl::OS2OnNotify(idCtrl, lParam, result); + } +*/ + event.SetEventObject( this ); + event.SetEventType(eventType); + event.SetInt(idCtrl) ; + + return ProcessEvent(event); } +// Responds to colour changes, and passes event on to children. +void wxTabCtrl::OnSysColourChanged(wxSysColourChangedEvent& event) +{ + // TODO: +/* + m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), + GetGValue(GetSysColor(COLOR_BTNFACE)), + GetBValue(GetSysColor(COLOR_BTNFACE))); + + Refresh(); +*/ + // Propagate the event to the non-top-level children + wxWindow::OnSysColourChanged(event); +} + + // Delete all items bool wxTabCtrl::DeleteAllItems() { @@ -191,6 +280,73 @@ void wxTabCtrl::SetPadding(const wxSize& padding) // TODO } +#if 0 +// These are the default colors used to map the bitmap colors +// to the current system colors + +#define BGR_BUTTONTEXT (RGB(000,000,000)) // black +#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey +#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey +#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white +#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue +#define BGR_BACKGROUND (RGB(255,000,255)) // magenta + +void wxMapBitmap(HBITMAP hBitmap, int width, int height) +{ + COLORMAP ColorMap[] = { + {BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black + {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey + {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey + {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white + {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue + {BGR_BACKGROUND, COLOR_WINDOW} // magenta + }; + + int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP)); + int n; + for ( n = 0; n < NUM_MAPS; n++) + { + ColorMap[n].to = ::GetSysColor(ColorMap[n].to); + } + + HBITMAP hbmOld; + HDC hdcMem = CreateCompatibleDC(NULL); + + if (hdcMem) + { + hbmOld = SelectObject(hdcMem, hBitmap); + + int i, j, k; + for ( i = 0; i < width; i++) + { + for ( j = 0; j < height; j++) + { + COLORREF pixel = ::GetPixel(hdcMem, i, j); +/* + BYTE red = GetRValue(pixel); + BYTE green = GetGValue(pixel); + BYTE blue = GetBValue(pixel); +*/ + + for ( k = 0; k < NUM_MAPS; k ++) + { + if ( ColorMap[k].from == pixel ) + { + /* COLORREF actualPixel = */ ::SetPixel(hdcMem, i, j, ColorMap[k].to); + break; + } + } + } + } + + + SelectObject(hdcMem, hbmOld); + DeleteObject(hdcMem); + } + +} +#endif + // Tab event IMPLEMENT_DYNAMIC_CLASS(wxTabEvent, wxCommandEvent) @@ -199,3 +355,4 @@ wxTabEvent::wxTabEvent(wxEventType commandType, int id): { } + diff --git a/src/os2/taskbar.cpp b/src/os2/taskbar.cpp index 5c91250cf0..723ec93a3d 100644 --- a/src/os2/taskbar.cpp +++ b/src/os2/taskbar.cpp @@ -2,69 +2,372 @@ // File: taskbar.cpp // Purpose: Implements wxTaskBarIcon class for manipulating icons on // the task bar. Optional. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "taskbar.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include "wx/defs.h" +#include "wx/window.h" +#include "wx/frame.h" +#include "wx/utils.h" +#include "wx/menu.h" +#endif + +#define INCL_PM +#include +#include +#include +#include + +MRESULT wxTaskBarIconWindowProc( HWND hWnd, UINT msg, MPARAM wParam, MPARAM lParam ); + +wxChar *wxTaskBarWindowClass = wxT("wxTaskBarWindowClass"); + +wxList wxTaskBarIcon::sm_taskBarIcons; +bool wxTaskBarIcon::sm_registeredClass = FALSE; +UINT wxTaskBarIcon::sm_taskbarMsg = 0; + + +#if !USE_SHARED_LIBRARY +BEGIN_EVENT_TABLE(wxTaskBarIcon, wxEvtHandler) + EVT_TASKBAR_MOVE (wxTaskBarIcon::_OnMouseMove) + EVT_TASKBAR_LEFT_DOWN (wxTaskBarIcon::_OnLButtonDown) + EVT_TASKBAR_LEFT_UP (wxTaskBarIcon::_OnLButtonUp) + EVT_TASKBAR_RIGHT_DOWN (wxTaskBarIcon::_OnRButtonDown) + EVT_TASKBAR_RIGHT_UP (wxTaskBarIcon::_OnRButtonUp) + EVT_TASKBAR_LEFT_DCLICK (wxTaskBarIcon::_OnLButtonDClick) + EVT_TASKBAR_RIGHT_DCLICK (wxTaskBarIcon::_OnRButtonDClick) +END_EVENT_TABLE() + +IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler) #endif -#include -wxTaskBarIcon::wxTaskBarIcon() +wxTaskBarIcon::wxTaskBarIcon(void) { - // TODO + m_hWnd = 0; + m_iconAdded = FALSE; + + AddObject(this); +// TODO: +/* + if (RegisterWindowClass()) + m_hWnd = CreateTaskBarWindow(); +*/ } -wxTaskBarIcon::~wxTaskBarIcon() +wxTaskBarIcon::~wxTaskBarIcon(void) { - // TODO +// TODO: +/* + RemoveObject(this); + + if (m_iconAdded) + { + RemoveIcon(); + } + + if (m_hWnd) + { + ::DestroyWindow((HWND) m_hWnd); + m_hWnd = 0; + } +*/ } // Operations bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip) { - // TODO + if (!IsOK()) + return FALSE; +// TODO: +/* + NOTIFYICONDATA notifyData; + + memset(¬ifyData, 0, sizeof(notifyData)); + notifyData.cbSize = sizeof(notifyData); + notifyData.hWnd = (HWND) m_hWnd; + notifyData.uCallbackMessage = sm_taskbarMsg; + notifyData.uFlags = NIF_MESSAGE ; + if (icon.Ok()) + { + notifyData.uFlags |= NIF_ICON; + notifyData.hIcon = (HICON) icon.GetHICON(); + } + + if (((const wxChar*) tooltip != NULL) && (tooltip != wxT(""))) + { + notifyData.uFlags |= NIF_TIP ; + lstrcpyn(notifyData.szTip, WXSTRINGCAST tooltip, sizeof(notifyData.szTip)); + } + + notifyData.uID = 99; + + if (m_iconAdded) + return (Shell_NotifyIcon(NIM_MODIFY, & notifyData) != 0); + else + { + m_iconAdded = (Shell_NotifyIcon(NIM_ADD, & notifyData) != 0); + return m_iconAdded; + } +*/ return FALSE; } -bool wxTaskBarIcon::RemoveIcon() +bool wxTaskBarIcon::RemoveIcon(void) { - // TODO + if (!m_iconAdded) + return FALSE; +//TODO: +/* + NOTIFYICONDATA notifyData; + + memset(¬ifyData, 0, sizeof(notifyData)); + notifyData.cbSize = sizeof(notifyData); + notifyData.hWnd = (HWND) m_hWnd; + notifyData.uCallbackMessage = sm_taskbarMsg; + notifyData.uFlags = NIF_MESSAGE; + notifyData.hIcon = 0 ; // hIcon; + notifyData.uID = 99; + m_iconAdded = FALSE; + + return (Shell_NotifyIcon(NIM_DELETE, & notifyData) != 0); +*/ return FALSE; } +bool wxTaskBarIcon::PopupMenu(wxMenu *menu) //, int x, int y); +{ + // OK, so I know this isn't thread-friendly, but + // what to do? We need this check. + + static bool s_inPopup = FALSE; + + if (s_inPopup) + return FALSE; + + s_inPopup = TRUE; + + bool rval = FALSE; + wxWindow* win; + int x, y; + wxGetMousePosition(&x, &y); + + // is wxFrame the best window type to use??? + win = new wxFrame(NULL, -1, "", wxPoint(x,y), wxSize(-1,-1), 0); + win->PushEventHandler(this); + + // Remove from record of top-level windows, or will confuse wxWindows + // if we try to exit right now. + wxTopLevelWindows.DeleteObject(win); + + menu->UpdateUI(); + + rval = win->PopupMenu(menu, 0, 0); + + win->PopEventHandler(FALSE); + win->Destroy(); + delete win; + + s_inPopup = FALSE; + + return rval; +} + // Overridables -void wxTaskBarIcon::OnMouseMove() +void wxTaskBarIcon::OnMouseMove(wxEvent&) { } -void wxTaskBarIcon::OnLButtonDown() +void wxTaskBarIcon::OnLButtonDown(wxEvent&) { } -void wxTaskBarIcon::OnLButtonUp() +void wxTaskBarIcon::OnLButtonUp(wxEvent&) { } -void wxTaskBarIcon::OnRButtonDown() +void wxTaskBarIcon::OnRButtonDown(wxEvent&) { } -void wxTaskBarIcon::OnRButtonUp() +void wxTaskBarIcon::OnRButtonUp(wxEvent&) { } -void wxTaskBarIcon::OnLButtonDClick() +void wxTaskBarIcon::OnLButtonDClick(wxEvent&) { } -void wxTaskBarIcon::OnRButtonDClick() +void wxTaskBarIcon::OnRButtonDClick(wxEvent&) +{ +} + +void wxTaskBarIcon::_OnMouseMove(wxEvent& e) { OnMouseMove(e); } +void wxTaskBarIcon::_OnLButtonDown(wxEvent& e) { OnLButtonDown(e); } +void wxTaskBarIcon::_OnLButtonUp(wxEvent& e) { OnLButtonUp(e); } +void wxTaskBarIcon::_OnRButtonDown(wxEvent& e) { OnRButtonDown(e); } +void wxTaskBarIcon::_OnRButtonUp(wxEvent& e) { OnRButtonUp(e); } +void wxTaskBarIcon::_OnLButtonDClick(wxEvent& e) { OnLButtonDClick(e); } +void wxTaskBarIcon::_OnRButtonDClick(wxEvent& e) { OnRButtonDClick(e); } + + +wxTaskBarIcon* wxTaskBarIcon::FindObjectForHWND(WXHWND hWnd) +{ + wxNode*node = sm_taskBarIcons.First(); + while (node) + { + wxTaskBarIcon* obj = (wxTaskBarIcon*) node->Data(); + if (obj->GetHWND() == hWnd) + return obj; + node = node->Next(); + } + return NULL; +} + +void wxTaskBarIcon::AddObject(wxTaskBarIcon* obj) +{ + sm_taskBarIcons.Append(obj); +} + +void wxTaskBarIcon::RemoveObject(wxTaskBarIcon* obj) +{ + sm_taskBarIcons.DeleteObject(obj); +} + +bool wxTaskBarIcon::RegisterWindowClass() +{ + if (sm_registeredClass) + return TRUE; + + // Also register the taskbar message here +// TODO: +/* + sm_taskbarMsg = ::RegisterWindowMessage(wxT("wxTaskBarIconMessage")); + + WNDCLASS wc; + bool rc; + + HINSTANCE hInstance = GetModuleHandle(NULL); + + // + // set up and register window class + // + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC) wxTaskBarIconWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = 0; + wc.hCursor = 0; + wc.hbrBackground = 0; + wc.lpszMenuName = NULL; + wc.lpszClassName = wxTaskBarWindowClass ; + rc = (::RegisterClass( &wc ) != 0); + + sm_registeredClass = (rc != 0); + + return( (rc != 0) ); +*/ + return FALSE; +} + +WXHWND wxTaskBarIcon::CreateTaskBarWindow() +{ +// TODO: +/* + HINSTANCE hInstance = GetModuleHandle(NULL); + + HWND hWnd = CreateWindowEx (0, wxTaskBarWindowClass, + wxT("wxTaskBarWindow"), + WS_OVERLAPPED, + 0, + 0, + 10, + 10, + NULL, + (HMENU) 0, + hInstance, + NULL); + + return (WXHWND) hWnd; +*/ + return (WXHWND)0; +} + +MRESULT wxTaskBarIcon::WindowProc( WXHWND hWnd, UINT msg, MPARAM wParam, MPARAM lParam ) +{ + wxEventType eventType = 0; +// TODO: +/* + if (msg != sm_taskbarMsg) + return DefWindowProc((HWND) hWnd, msg, wParam, lParam); + + switch (lParam) + { + case WM_LBUTTONDOWN: + eventType = wxEVT_TASKBAR_LEFT_DOWN; + break; + + case WM_LBUTTONUP: + eventType = wxEVT_TASKBAR_LEFT_UP; + break; + + case WM_RBUTTONDOWN: + eventType = wxEVT_TASKBAR_RIGHT_DOWN; + break; + + case WM_RBUTTONUP: + eventType = wxEVT_TASKBAR_RIGHT_UP; + break; + + case WM_LBUTTONDBLCLK: + eventType = wxEVT_TASKBAR_LEFT_DCLICK; + break; + + case WM_RBUTTONDBLCLK: + eventType = wxEVT_TASKBAR_RIGHT_DCLICK; + break; + + case WM_MOUSEMOVE: + eventType = wxEVT_TASKBAR_MOVE; + break; + + default: + break; + } +*/ + if (eventType) + { + wxEvent event; + event.SetEventType(eventType); + event.SetEventObject(this); + + ProcessEvent(event); + } + return 0; +} + +MRESULT wxTaskBarIconWindowProc( + HWND hWnd +, UINT msg +, MPARAM wParam +, MPARAM lParam +) { + wxTaskBarIcon* obj = wxTaskBarIcon::FindObjectForHWND((WXHWND) hWnd); + if (obj) + return obj->WindowProc((WXHWND) hWnd, msg, wParam, lParam); + else + return (MRESULT)0; +// return DefWindowProc(hWnd, msg, wParam, lParam); } diff --git a/src/os2/textctrl.cpp b/src/os2/textctrl.cpp index 720e6082be..82022466ef 100644 --- a/src/os2/textctrl.cpp +++ b/src/os2/textctrl.cpp @@ -1,40 +1,60 @@ ///////////////////////////////////////////////////////////////////////////// // Name: textctrl.cpp // Purpose: wxTextCtrl -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "textctrl.h" +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/textctrl.h" + #include "wx/settings.h" + #include "wx/brush.h" + #include "wx/utils.h" + #include "wx/log.h" #endif -#include -#include -#include +#if wxUSE_CLIPBOARD + #include "wx/app.h" + #include "wx/clipbrd.h" +#endif -#include "wx/textctrl.h" -#include "wx/settings.h" -#include "wx/filefn.h" -#include "wx/utils.h" +#include "wx/textfile.h" + +#include "wx/os2/private.h" + +#include +#include +#include -#if defined(__BORLANDC__) && !defined(__WIN32__) -#include +#if wxUSE_IOSTREAMH +# include #else -#ifndef __GNUWIN32__ -#include -#endif +# include #endif #if !USE_SHARED_LIBRARY + +// ---------------------------------------------------------------------------- +// event tables and other macros +// ---------------------------------------------------------------------------- + IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) - EVT_DROP_FILES(wxTextCtrl::OnDropFiles) + EVT_CHAR(wxTextCtrl::OnChar) + EVT_DROP_FILES(wxTextCtrl::OnDropFiles) + EVT_MENU(wxID_CUT, wxTextCtrl::OnCut) EVT_MENU(wxID_COPY, wxTextCtrl::OnCopy) EVT_MENU(wxID_PASTE, wxTextCtrl::OnPaste) @@ -47,299 +67,584 @@ BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) EVT_UPDATE_UI(wxID_UNDO, wxTextCtrl::OnUpdateUndo) EVT_UPDATE_UI(wxID_REDO, wxTextCtrl::OnUpdateRedo) END_EVENT_TABLE() -#endif -// Text item +#endif // USE_SHARED_LIBRARY + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// creation +// ---------------------------------------------------------------------------- + wxTextCtrl::wxTextCtrl() -#ifndef NO_TEXT_WINDOW_STREAM - :streambuf() -#endif { - m_fileName = ""; } bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, long style, - const wxValidator& validator, - const wxString& name) -{ - m_fileName = ""; - SetName(name); - SetValidator(validator); - if (parent) parent->AddChild(this); + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) +{ + // base initialization + if ( !CreateBase(parent, id, pos, size, style, validator, name) ) + return FALSE; - m_windowStyle = style; + // Validator was set in CreateBase + //SetValidator(validator); + if ( parent ) + parent->AddChild(this); - if ( id == -1 ) - m_windowId = (int)NewControlId(); + // set colours + SetupColours(); + + // translate wxWin style flags to MSW ones, checking for consistency while + // doing it +// TODO: +/* + long msStyle = ES_LEFT | WS_VISIBLE | WS_CHILD | WS_TABSTOP; + if ( m_windowStyle & wxTE_MULTILINE ) + { + wxASSERT_MSG( !(m_windowStyle & wxTE_PROCESS_ENTER), + wxT("wxTE_PROCESS_ENTER style is ignored for multiline " + "text controls (they always process it)") ); + + msStyle |= ES_MULTILINE | ES_WANTRETURN; + if ((m_windowStyle & wxTE_NO_VSCROLL) == 0) + msStyle |= WS_VSCROLL; + m_windowStyle |= wxTE_PROCESS_ENTER; + } else - m_windowId = id; + msStyle |= ES_AUTOHSCROLL; + + if (m_windowStyle & wxHSCROLL) + msStyle |= (WS_HSCROLL | ES_AUTOHSCROLL); + + if (m_windowStyle & wxTE_READONLY) + msStyle |= ES_READONLY; + + if (m_windowStyle & wxHSCROLL) + msStyle |= (WS_HSCROLL | ES_AUTOHSCROLL); + if (m_windowStyle & wxTE_PASSWORD) // hidden input + msStyle |= ES_PASSWORD; + + // we always want the characters and the arrows + m_lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS; + + // we may have several different cases: + // 1. normal case: both TAB and ENTER are used for dialog navigation + // 2. ctrl which wants TAB for itself: ENTER is used to pass to the next + // control in the dialog + // 3. ctrl which wants ENTER for itself: TAB is used for dialog navigation + // 4. ctrl which wants both TAB and ENTER: Ctrl-ENTER is used to pass to + // the next control + if ( m_windowStyle & wxTE_PROCESS_ENTER ) + m_lDlgCode |= DLGC_WANTMESSAGE; + if ( m_windowStyle & wxTE_PROCESS_TAB ) + m_lDlgCode |= DLGC_WANTTAB; + + // do create the control - either an EDIT or RICHEDIT + const wxChar *windowClass = wxT("EDIT"); + + bool want3D; + WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D); + + // Even with extended styles, need to combine with WS_BORDER for them to + // look right. + if ( want3D || wxStyleHasBorder(m_windowStyle) ) + msStyle |= WS_BORDER; + + // NB: don't use pos and size as CreateWindowEx arguments because they + // might be -1 in which case we should use the default values (and + // SetSize called below takes care of it) + m_hWnd = (WXHWND)::CreateWindowEx(exStyle, + windowClass, + NULL, + msStyle, + 0, 0, 0, 0, + GetHwndOf(parent), + (HMENU)m_windowId, + wxGetInstance(), + NULL); + + wxCHECK_MSG( m_hWnd, FALSE, wxT("Failed to create text ctrl") ); +*/ + SubclassWin(GetHWND()); + + // set font, position, size and initial value + wxFont& fontParent = parent->GetFont(); + if ( fontParent.Ok() ) + { + SetFont(fontParent); + } + else + { + SetFont(wxSystemSettings::GetSystemFont(wxSYS_SYSTEM_FONT)); + } + + SetSize(pos.x, pos.y, size.x, size.y); return TRUE; } +// Make sure the window style (etc.) reflects the HWND style (roughly) +void wxTextCtrl::AdoptAttributesFromHWND() +{ + wxWindow::AdoptAttributesFromHWND(); + + HWND hWnd = GetHwnd(); + // TODO: + /* + long style = GetWindowLong(hWnd, GWL_STYLE); + + if (style & ES_MULTILINE) + m_windowStyle |= wxTE_MULTILINE; + if (style & ES_PASSWORD) + m_windowStyle |= wxTE_PASSWORD; + if (style & ES_READONLY) + m_windowStyle |= wxTE_READONLY; + if (style & ES_WANTRETURN) + m_windowStyle |= wxTE_PROCESS_ENTER; + */ +} + +void wxTextCtrl::SetupColours() +{ + // FIXME why is bg colour not inherited from parent? + SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + SetForegroundColour(GetParent()->GetForegroundColour()); +} + +// ---------------------------------------------------------------------------- +// set/get the controls text +// ---------------------------------------------------------------------------- + wxString wxTextCtrl::GetValue() const { - // TODO - return wxString(""); + return wxGetWindowText(GetHWND()); } void wxTextCtrl::SetValue(const wxString& value) { - // TODO +// TODO: +/* + wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Dos); + + SetWindowText(GetHwnd(), valueDos); + + AdjustSpaceLimit(); +*/ } -void wxTextCtrl::SetSize(int x, int y, int width, int height, int sizeFlags) +void wxTextCtrl::WriteText(const wxString& value) { - // TODO +// TODO: +/* + wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Dos); + + SendMessage(GetHwnd(), EM_REPLACESEL, 0, (LPARAM)valueDos.c_str()); + + AdjustSpaceLimit(); +*/ } +void wxTextCtrl::AppendText(const wxString& text) +{ +// TODO: +/* + SetInsertionPointEnd(); + WriteText(text); +*/ +} + +void wxTextCtrl::Clear() +{ +// SetWindowText(GetHwnd(), wxT("")); +} + +// ---------------------------------------------------------------------------- // Clipboard operations +// ---------------------------------------------------------------------------- + void wxTextCtrl::Copy() { - // TODO + if (CanCopy()) + { + HWND hWnd = GetHwnd(); +// SendMessage(hWnd, WM_COPY, 0, 0L); + } } void wxTextCtrl::Cut() { - // TODO + if (CanCut()) + { + HWND hWnd = GetHwnd(); +// SendMessage(hWnd, WM_CUT, 0, 0L); + } } void wxTextCtrl::Paste() { - // TODO + if (CanPaste()) + { + HWND hWnd = GetHwnd(); +// SendMessage(hWnd, WM_PASTE, 0, 0L); + } +} + +bool wxTextCtrl::CanCopy() const +{ + // Can copy if there's a selection + long from, to; +// GetSelection(& from, & to); + return (from != to); +} + +bool wxTextCtrl::CanCut() const +{ + // Can cut if there's a selection + long from, to; +// GetSelection(& from, & to); + return (from != to); +} + +bool wxTextCtrl::CanPaste() const +{ + if (!IsEditable()) + return FALSE; + + // Standard edit control: check for straight text on clipboard + bool isTextAvailable = FALSE; +//TODO: +/* + if ( ::OpenClipboard(GetHwndOf(wxTheApp->GetTopWindow())) ) + { + isTextAvailable = (::IsClipboardFormatAvailable(CF_TEXT) != 0); + ::CloseClipboard(); + } +*/ + return isTextAvailable; } +// ---------------------------------------------------------------------------- +// Accessors +// ---------------------------------------------------------------------------- + void wxTextCtrl::SetEditable(bool editable) { - // TODO + HWND hWnd = GetHwnd(); +// SendMessage(hWnd, EM_SETREADONLY, (WPARAM)!editable, (LPARAM)0L); } void wxTextCtrl::SetInsertionPoint(long pos) { - // TODO +// TODO: +/* + HWND hWnd = GetHwnd(); + { + SendMessage(hWnd, EM_SETSEL, pos, pos); + SendMessage(hWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); + } + static const char *nothing = ""; + SendMessage(hWnd, EM_REPLACESEL, 0, (LPARAM)nothing); +*/ } void wxTextCtrl::SetInsertionPointEnd() { +// TODO: +/* long pos = GetLastPosition(); SetInsertionPoint(pos); +*/ } long wxTextCtrl::GetInsertionPoint() const { - // TODO +// TODO: +/* + DWORD Pos = (DWORD)SendMessage(GetHwnd(), EM_GETSEL, 0, 0L); + return Pos & 0xFFFF; +*/ return 0; } long wxTextCtrl::GetLastPosition() const { - // TODO - return 0; -} + HWND hWnd = GetHwnd(); -void wxTextCtrl::Replace(long from, long to, const wxString& value) -{ - // TODO -} +// TODO: +/* + // Will always return a number > 0 (according to docs) + int noLines = (int)SendMessage(hWnd, EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0L); -void wxTextCtrl::Remove(long from, long to) -{ - // TODO -} + // This gets the char index for the _beginning_ of the last line + int charIndex = (int)SendMessage(hWnd, EM_LINEINDEX, (WPARAM)(noLines-1), (LPARAM)0L); -void wxTextCtrl::SetSelection(long from, long to) -{ - // TODO + // Get number of characters in the last line. We'll add this to the character + // index for the last line, 1st position. + int lineLength = (int)SendMessage(hWnd, EM_LINELENGTH, (WPARAM)charIndex, (LPARAM)0L); + + return (long)(charIndex + lineLength); +*/ + return 0L; } -bool wxTextCtrl::LoadFile(const wxString& file) +// If the return values from and to are the same, there is no +// selection. +void wxTextCtrl::GetSelection(long* from, long* to) const { - if (!wxFileExists(file)) - return FALSE; + DWORD dwStart, dwEnd; + MPARAM wParam = (MPARAM) (DWORD*) & dwStart; // receives starting position + MPARAM lParam = (MPARAM) (DWORD*) & dwEnd; // receives ending position - m_fileName = file; +// ::SendMessage(GetHwnd(), EM_GETSEL, wParam, lParam); - Clear(); + *from = dwStart; + *to = dwEnd; +} - ifstream input((char*) (const char*) file, ios::nocreate | ios::in); +bool wxTextCtrl::IsEditable() const +{ +// TODO: +/* + long style = ::GetWindowLong(GetHwnd(), GWL_STYLE); - if (!input.bad()) - { - struct stat stat_buf; - if (stat(file, &stat_buf) < 0) - return FALSE; - // This may need to be a bigger buffer than the file size suggests, - // if it's a UNIX file. Give it an extra 1000 just in case. - char *tmp_buffer = (char*)malloc((size_t)(stat_buf.st_size+1+1000)); - long no_lines = 0; - long pos = 0; - while (!input.eof() && input.peek() != EOF) - { - input.getline(wxBuffer, 500); - int len = strlen(wxBuffer); - wxBuffer[len] = 13; - wxBuffer[len+1] = 10; - wxBuffer[len+2] = 0; - strcpy(tmp_buffer+pos, wxBuffer); - pos += strlen(wxBuffer); - no_lines++; - } - - // TODO add line - - free(tmp_buffer); - - return TRUE; - } + return ((style & ES_READONLY) == 0); +*/ return FALSE; } -// If file is null, try saved file name first -// Returns TRUE if succeeds. -bool wxTextCtrl::SaveFile(const wxString& file) +// ---------------------------------------------------------------------------- +// Editing +// ---------------------------------------------------------------------------- + +void wxTextCtrl::Replace(long from, long to, const wxString& value) { - wxString theFile(file); - if (theFile == "") - theFile = m_fileName; - if (theFile == "") - return FALSE; - m_fileName = theFile; +#if wxUSE_CLIPBOARD + HWND hWnd = GetHwnd(); + long fromChar = from; + long toChar = to; - ofstream output((char*) (const char*) theFile); - if (output.bad()) - return FALSE; + // Set selection and remove it +// SendMessage(hWnd, EM_SETSEL, fromChar, toChar); +// SendMessage(hWnd, WM_CUT, (WPARAM)0, (LPARAM)0); - // TODO get and save text + // Now replace with 'value', by pasting. + wxSetClipboardData(wxDF_TEXT, (wxObject *) (const wxChar *)value, 0, 0); - return FALSE; + // Paste into edit control +// SendMessage(hWnd, WM_PASTE, (WPARAM)0, (LPARAM)0L); +#else + wxFAIL_MSG("wxTextCtrl::Replace not implemented if wxUSE_CLIPBOARD is 0."); +#endif } -void wxTextCtrl::WriteText(const wxString& text) +void wxTextCtrl::Remove(long from, long to) { - // TODO write text to control + HWND hWnd = GetHwnd(); + long fromChar = from; + long toChar = to; + + // Cut all selected text +// SendMessage(hWnd, EM_SETSEL, fromChar, toChar); +// SendMessage(hWnd, WM_CUT, (WPARAM)0, (LPARAM)0); } -void wxTextCtrl::AppendText(const wxString& text) +void wxTextCtrl::SetSelection(long from, long to) { - // TODO append text to control + HWND hWnd = GetHwnd(); + long fromChar = from; + long toChar = to; + + // if from and to are both -1, it means (in wxWindows) that all text should + // be selected. Translate into Windows convention + if ((from == -1) && (to == -1)) + { + fromChar = 0; + toChar = -1; + } + +// SendMessage(hWnd, EM_SETSEL, (WPARAM)fromChar, (LPARAM)toChar); +// SendMessage(hWnd, EM_SCROLLCARET, (WPARAM)0, (LPARAM)0); } -void wxTextCtrl::Clear() +bool wxTextCtrl::LoadFile(const wxString& file) { - // TODO +// TODO: +/* + if ( wxTextCtrlBase::LoadFile(file) ) + { + // update the size limit if needed + AdjustSpaceLimit(); + + return TRUE; + } +*/ + return FALSE; } bool wxTextCtrl::IsModified() const { - // TODO +// return (SendMessage(GetHwnd(), EM_GETMODIFY, 0, 0) != 0); return FALSE; } // Makes 'unmodified' void wxTextCtrl::DiscardEdits() { - // TODO +// SendMessage(GetHwnd(), EM_SETMODIFY, FALSE, 0L); } int wxTextCtrl::GetNumberOfLines() const { - // TODO +// return (int)SendMessage(GetHwnd(), EM_GETLINECOUNT, (WPARAM)0, (LPARAM)0); return 0; } long wxTextCtrl::XYToPosition(long x, long y) const { - // TODO - return 0; + HWND hWnd = GetHwnd(); + + // This gets the char index for the _beginning_ of this line +// TODO: +/* + int charIndex = (int)SendMessage(hWnd, EM_LINEINDEX, (WPARAM)y, (LPARAM)0); + return (long)(x + charIndex); +*/ + return 0L; } -void wxTextCtrl::PositionToXY(long pos, long *x, long *y) const +bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const { - // TODO + HWND hWnd = GetHwnd(); + + // This gets the line number containing the character + int lineNo; +// lineNo = (int)SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)pos, 0); + + if ( lineNo == -1 ) + { + // no such line + return FALSE; + } + + // This gets the char index for the _beginning_ of this line + int charIndex = 0; // TODO: (int)SendMessage(hWnd, EM_LINEINDEX, (WPARAM)lineNo, (LPARAM)0); + if ( charIndex == -1 ) + { + return FALSE; + } + + // The X position must therefore be the different between pos and charIndex + if ( x ) + *x = (long)(pos - charIndex); + if ( y ) + *y = (long)lineNo; + + return TRUE; } void wxTextCtrl::ShowPosition(long pos) { - // TODO + HWND hWnd = GetHwnd(); + + // To scroll to a position, we pass the number of lines and characters + // to scroll *by*. This means that we need to: + // (1) Find the line position of the current line. + // (2) Find the line position of pos. + // (3) Scroll by (pos - current). + // For now, ignore the horizontal scrolling. + + // Is this where scrolling is relative to - the line containing the caret? + // Or is the first visible line??? Try first visible line. +// int currentLineLineNo1 = (int)SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)-1, (LPARAM)0L); + +// TODO: +/* + int currentLineLineNo = (int)SendMessage(hWnd, EM_GETFIRSTVISIBLELINE, (WPARAM)0, (LPARAM)0L); + + int specifiedLineLineNo = (int)SendMessage(hWnd, EM_LINEFROMCHAR, (WPARAM)pos, (LPARAM)0L); + + int linesToScroll = specifiedLineLineNo - currentLineLineNo; + + if (linesToScroll != 0) + (void)SendMessage(hWnd, EM_LINESCROLL, (WPARAM)0, (LPARAM)linesToScroll); +*/ } int wxTextCtrl::GetLineLength(long lineNo) const { - // TODO +// TODO: +/* + + long charIndex = XYToPosition(0, lineNo); + int len = (int)SendMessage(GetHwnd(), EM_LINELENGTH, charIndex, 0); + return len; +*/ return 0; } wxString wxTextCtrl::GetLineText(long lineNo) const { - // TODO - return wxString(""); -} + size_t len = (size_t)GetLineLength(lineNo) + 1; + char *buf = (char *)malloc(len); + *(WORD *)buf = len; + int noChars = 0; // TODO:(int)SendMessage(GetHwnd(), EM_GETLINE, lineNo, (LPARAM)buf); + buf[noChars] = 0; -bool wxTextCtrl::CanCopy() const -{ - // Can copy if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to) ; -} + wxString str(buf); -bool wxTextCtrl::CanCut() const -{ - // Can cut if there's a selection - long from, to; - GetSelection(& from, & to); - return (from != to) ; -} + free(buf); -bool wxTextCtrl::CanPaste() const -{ - return IsEditable() ; + return str; } +// ---------------------------------------------------------------------------- // Undo/redo +// ---------------------------------------------------------------------------- + void wxTextCtrl::Undo() { - // TODO + if (CanUndo()) + { +// ::SendMessage(GetHwnd(), EM_UNDO, 0, 0); + } } void wxTextCtrl::Redo() { - // TODO + if (CanRedo()) + { + // Same as Undo, since Undo undoes the undo, i.e. a redo. +// ::SendMessage(GetHwnd(), EM_UNDO, 0, 0); + } } bool wxTextCtrl::CanUndo() const { - // TODO +// return (::SendMessage(GetHwnd(), EM_CANUNDO, 0, 0) != 0); return FALSE; } bool wxTextCtrl::CanRedo() const { - // TODO +// return (::SendMessage(GetHwnd(), EM_CANUNDO, 0, 0) != 0); return FALSE; } -// If the return values from and to are the same, there is no -// selection. -void wxTextCtrl::GetSelection(long* from, long* to) const -{ - // TODO - *from = 0; - *to = 0; -} - -bool wxTextCtrl::IsEditable() const -{ - // TODO - return FALSE; -} +// ---------------------------------------------------------------------------- +// implemenation details +// ---------------------------------------------------------------------------- void wxTextCtrl::Command(wxCommandEvent & event) { - SetValue (event.GetString()); + SetValue(event.GetString()); ProcessCommand (event); } @@ -352,161 +657,166 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event) } } -// The streambuf code was partly taken from chapter 3 by Jerry Schwarz of -// AT&T's "C++ Lanuage System Release 3.0 Library Manual" - Stein Somers - -//========================================================================= -// Called then the buffer is full (gcc 2.6.3) -// or when "endl" is output (Borland 4.5) -//========================================================================= -// Class declaration using multiple inheritance doesn't work properly for -// Borland. See note in wb_text.h. -#ifndef NO_TEXT_WINDOW_STREAM -int wxTextCtrl::overflow(int c) -{ - // Make sure there is a holding area - if ( allocate()==EOF ) - { - wxError("Streambuf allocation failed","Internal error"); - return EOF; - } - - // Verify that there are no characters in get area - if ( gptr() && gptr() < egptr() ) - { - wxError("Who's trespassing my get area?","Internal error"); - return EOF; - } - - // Reset get area - setg(0,0,0); - - // Make sure there is a put area - if ( ! pptr() ) - { -/* This doesn't seem to be fatal so comment out error message */ -// wxError("Put area not opened","Internal error"); - setp( base(), base() ); - } - - // Determine how many characters have been inserted but no consumed - int plen = pptr() - pbase(); - - // Now Jerry relies on the fact that the buffer is at least 2 chars - // long, but the holding area "may be as small as 1" ??? - // And we need an additional \0, so let's keep this inefficient but - // safe copy. - - // If c!=EOF, it is a character that must also be comsumed - int xtra = c==EOF? 0 : 1; - - // Write temporary C-string to wxTextWindow - { - char *txt = new char[plen+xtra+1]; - memcpy(txt, pbase(), plen); - txt[plen] = (char)c; // append c - txt[plen+xtra] = '\0'; // append '\0' or overwrite c - // If the put area already contained \0, output will be truncated there - AppendText(txt); - delete[] txt; - } - - // Reset put area - setp(pbase(), epptr()); - -#if defined(__WATCOMC__) - return __NOT_EOF; -#elif defined(zapeof) // HP-UX (all cfront based?) - return zapeof(c); -#else - return c!=EOF ? c : 0; // this should make everybody happy -#endif -} +WXHBRUSH wxTextCtrl::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, + WXUINT message, WXWPARAM wParam, + WXLPARAM lParam) +{ + HDC hdc = (HDC)pDC; +// TODO: +/* + SetBkMode(hdc, GetParent()->GetTransparentBackground() ? TRANSPARENT + : OPAQUE); -//========================================================================= -// called then "endl" is output (gcc) or then explicit sync is done (Borland) -//========================================================================= -int wxTextCtrl::sync() -{ - // Verify that there are no characters in get area - if ( gptr() && gptr() < egptr() ) - { - wxError("Who's trespassing my get area?","Internal error"); - return EOF; - } - - if ( pptr() && pptr() > pbase() ) return overflow(EOF); - - return 0; -/* OLD CODE - int len = pptr() - pbase(); - char *txt = new char[len+1]; - strncpy(txt, pbase(), len); - txt[len] = '\0'; - (*this) << txt; - setp(pbase(), epptr()); - delete[] txt; - return 0; + ::SetBkColor(hdc, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue())); + ::SetTextColor(hdc, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue())); */ -} + wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID); -//========================================================================= -// Should not be called by a "ostream". Used by a "istream" -//========================================================================= -int wxTextCtrl::underflow() -{ - return EOF; + return (WXHBRUSH) backgroundBrush->GetResourceHandle(); } -#endif -wxTextCtrl& wxTextCtrl::operator<<(const wxString& s) +void wxTextCtrl::OnChar(wxKeyEvent& event) { - AppendText(s); - return *this; -} + switch ( event.KeyCode() ) + { +// TODO: +/* + case WXK_RETURN: + if ( !(m_windowStyle & wxTE_MULTILINE) ) + { + wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); + event.SetEventObject( this ); + if ( GetEventHandler()->ProcessEvent(event) ) + return; + } + //else: multiline controls need Enter for themselves + + break; + + case WXK_TAB: + // always produce navigation event - even if we process TAB + // ourselves the fact that we got here means that the user code + // decided to skip processing of this TAB - probably to let it + // do its default job. + // + // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is + // handled by Windows + { + wxNavigationKeyEvent eventNav; + eventNav.SetDirection(!event.ShiftDown()); + eventNav.SetWindowChange(FALSE); + eventNav.SetEventObject(this); + + if ( GetEventHandler()->ProcessEvent(eventNav) ) + return; + } + break; +*/ + default: + event.Skip(); + return; + } -wxTextCtrl& wxTextCtrl::operator<<(float f) -{ - wxString str; - str.Printf("%.2f", f); - AppendText(str); - return *this; + // don't just call event.Skip() because this will cause TABs and ENTERs + // be passed upwards and we don't always want this - instead process it + // right here + + // FIXME + event.Skip(); } -wxTextCtrl& wxTextCtrl::operator<<(double d) +bool wxTextCtrl::OS2Command(WXUINT param, WXWORD WXUNUSED(id)) { - wxString str; - str.Printf("%.2f", d); - AppendText(str); - return *this; + switch (param) + { +// TODO: +/* + case EN_SETFOCUS: + case EN_KILLFOCUS: + { + wxFocusEvent event(param == EN_KILLFOCUS ? wxEVT_KILL_FOCUS + : wxEVT_SET_FOCUS, + m_windowId); + event.SetEventObject( this ); + GetEventHandler()->ProcessEvent(event); + } + break; + + case EN_CHANGE: + { + wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, m_windowId); + wxString val(GetValue()); + if ( !val.IsNull() ) + event.m_commandString = WXSTRINGCAST val; + event.SetEventObject( this ); + ProcessCommand(event); + } + break; + + case EN_ERRSPACE: + // the text size limit has been hit - increase it + AdjustSpaceLimit(); + break; + + // the other notification messages are not processed + case EN_UPDATE: + case EN_MAXTEXT: + case EN_HSCROLL: + case EN_VSCROLL: +*/ + default: + return FALSE; + } + + // processed + return TRUE; } -wxTextCtrl& wxTextCtrl::operator<<(int i) +void wxTextCtrl::AdjustSpaceLimit() { - wxString str; - str.Printf("%d", i); - AppendText(str); - return *this; +// TODO: +/* + unsigned int len = ::GetWindowTextLength(GetHwnd()), + limit = ::SendMessage(GetHwnd(), EM_GETLIMITTEXT, 0, 0); + if ( len > limit ) + { + limit = len + 0x8000; // 32Kb + + if ( limit > 0xffff ) + ::SendMessage(GetHwnd(), EM_LIMITTEXT, 0, limit); + else + ::SendMessage(GetHwnd(), EM_LIMITTEXT, limit, 0); + } +*/ } -wxTextCtrl& wxTextCtrl::operator<<(long i) +bool wxTextCtrl::AcceptsFocus() const { - wxString str; - str.Printf("%ld", i); - AppendText(str); - return *this; + // we don't want focus if we can't be edited + return IsEditable() && wxControl::AcceptsFocus(); } -wxTextCtrl& wxTextCtrl::operator<<(const char c) +wxSize wxTextCtrl::DoGetBestSize() { - char buf[2]; + int cx, cy; + wxGetCharSize(GetHWND(), &cx, &cy, &GetFont()); - buf[0] = c; - buf[1] = 0; - AppendText(buf); - return *this; + int wText = DEFAULT_ITEM_WIDTH; + + int hText = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy); + if ( m_windowStyle & wxTE_MULTILINE ) + { + hText *= wxMin(GetNumberOfLines(), 5); + } + //else: for single line control everything is ok + + return wxSize(wText, hText); } +// ---------------------------------------------------------------------------- +// standard handlers for standard edit menu events +// ---------------------------------------------------------------------------- + void wxTextCtrl::OnCut(wxCommandEvent& event) { Cut(); @@ -556,3 +866,4 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event) { event.Enable( CanRedo() ); } + diff --git a/src/os2/thread.cpp b/src/os2/thread.cpp index 34ad1a4f14..c636e6e9ae 100644 --- a/src/os2/thread.cpp +++ b/src/os2/thread.cpp @@ -2,70 +2,143 @@ // Name: thread.cpp // Purpose: wxThread Implementation. For Unix ports, see e.g. src/gtk // Author: Original from Wolfram Gloger/Guilhem Lavaux -// Modified by: +// Modified by: David Webster // Created: 04/22/98 // RCS-ID: $Id$ // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998) // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "thread.h" -#endif +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- -#include "wx/module.h" -#include "wx/thread.h" -#include "wx/utils.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" #if wxUSE_THREADS -enum thread_state { - STATE_IDLE = 0, - STATE_RUNNING, - STATE_CANCELED, - STATE_EXITED +#include + +#define INCL_DOS +#include + +#include "wx/module.h" +#include "wx/thread.h" + +// the possible states of the thread ("=>" shows all possible transitions from +// this state) +enum wxThreadState +{ + STATE_NEW, // didn't start execution yet (=> RUNNING) + STATE_RUNNING, // thread is running (=> PAUSED, CANCELED) + STATE_PAUSED, // thread is temporarily suspended (=> RUNNING) + STATE_CANCELED, // thread should terminate a.s.a.p. (=> EXITED) + STATE_EXITED // thread is terminating }; -///////////////////////////////////////////////////////////////////////////// -// Static variables -///////////////////////////////////////////////////////////////////////////// +// ---------------------------------------------------------------------------- +// static variables +// ---------------------------------------------------------------------------- -wxMutex *wxMainMutex; // controls access to all GUI functions +// TLS index of the slot where we store the pointer to the current thread +static DWORD s_tlsThisThread = 0xFFFFFFFF; -///////////////////////////////////////////////////////////////////////////// -// Windows implementation -///////////////////////////////////////////////////////////////////////////// +// id of the main thread - the one which can call GUI functions without first +// calling wxMutexGuiEnter() +static DWORD s_idMainThread = 0; + +// if it's FALSE, some secondary thread is holding the GUI lock +static bool s_bGuiOwnedByMainThread = TRUE; -class wxMutexInternal { +// critical section which controls access to all GUI functions: any secondary +// thread (i.e. except the main one) must enter this crit section before doing +// any GUI calls +static wxCriticalSection *s_critsectGui = NULL; + +// critical section which protects s_nWaitingForGui variable +static wxCriticalSection *s_critsectWaitingForGui = NULL; + +// number of threads waiting for GUI in wxMutexGuiEnter() +static size_t s_nWaitingForGui = 0; + +// are we waiting for a thread termination? +static bool s_waitingForThread = FALSE; + +// ============================================================================ +// Windows implementation of thread classes +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxMutex implementation +// ---------------------------------------------------------------------------- +class wxMutexInternal +{ public: - // TODO: internal mutex handle + HANDLE p_mutex; }; wxMutex::wxMutex() { p_internal = new wxMutexInternal; - // TODO: create internal mutext handle +// p_internal->p_mutex = CreateMutex(NULL, FALSE, NULL); + if ( !p_internal->p_mutex ) + { + wxLogSysError(_("Can not create mutex.")); + } + m_locked = 0; } wxMutex::~wxMutex() { if (m_locked > 0) - wxDebugMsg("wxMutex warning: freeing a locked mutex (%d locks)\n", m_locked); - // TODO: free internal mutext handle + wxLogDebug(wxT("Warning: freeing a locked mutex (%d locks)."), m_locked); +// CloseHandle(p_internal->p_mutex); } wxMutexError wxMutex::Lock() { - // TODO + DWORD ret; + +// TODO: +/* + ret = WaitForSingleObject(p_internal->p_mutex, INFINITE); + switch ( ret ) + { + case WAIT_ABANDONED: + return wxMUTEX_BUSY; + + case WAIT_OBJECT_0: + // ok + break; + + case WAIT_FAILED: + wxLogSysError(_("Couldn't acquire a mutex lock")); + return wxMUTEX_MISC_ERROR; + + case WAIT_TIMEOUT: + default: + wxFAIL_MSG(wxT("impossible return value in wxMutex::Lock")); + } + m_locked++; +*/ return wxMUTEX_NO_ERROR; } wxMutexError wxMutex::TryLock() { - // TODO + DWORD ret; + +// TODO: +/* + ret = WaitForSingleObject(p_internal->p_mutex, 0); + if (ret == WAIT_TIMEOUT || ret == WAIT_ABANDONED) + return wxMUTEX_BUSY; + m_locked++; +*/ return wxMUTEX_NO_ERROR; } @@ -74,192 +147,750 @@ wxMutexError wxMutex::Unlock() if (m_locked > 0) m_locked--; - // TODO + BOOL ret = 0; // TODO: ReleaseMutex(p_internal->p_mutex); + if ( ret == 0 ) + { + wxLogSysError(_("Couldn't release a mutex")); + return wxMUTEX_MISC_ERROR; + } + return wxMUTEX_NO_ERROR; } -class wxConditionInternal { +// ---------------------------------------------------------------------------- +// wxCondition implementation +// ---------------------------------------------------------------------------- + +class wxConditionInternal +{ public: - // TODO: internal handle - int waiters; + HANDLE event; + int waiters; }; wxCondition::wxCondition() { p_internal = new wxConditionInternal; - // TODO: create internal handle +// TODO: +/* + p_internal->event = CreateEvent(NULL, FALSE, FALSE, NULL); + if ( !p_internal->event ) + { + wxLogSysError(_("Can not create event object.")); + } +*/ p_internal->waiters = 0; } wxCondition::~wxCondition() { - // TODO: destroy internal handle +// CloseHandle(p_internal->event); } void wxCondition::Wait(wxMutex& mutex) { mutex.Unlock(); p_internal->waiters++; - // TODO wait here +// WaitForSingleObject(p_internal->event, INFINITE); p_internal->waiters--; mutex.Lock(); } -bool wxCondition::Wait(wxMutex& mutex, unsigned long sec, +bool wxCondition::Wait(wxMutex& mutex, + unsigned long sec, unsigned long nsec) { + DWORD ret; + mutex.Unlock(); p_internal->waiters++; - - // TODO wait here +// ret = WaitForSingleObject(p_internal->event, (sec*1000)+(nsec/1000000)); p_internal->waiters--; mutex.Lock(); +// return (ret != WAIT_TIMEOUT); return FALSE; } void wxCondition::Signal() { - // TODO +// SetEvent(p_internal->event); } void wxCondition::Broadcast() { - // TODO + int i; + +// TODO: +/* + for (i=0;iwaiters;i++) + { + if ( SetEvent(p_internal->event) == 0 ) + { + wxLogSysError(_("Couldn't change the state of event object.")); + } + } +*/ } -class wxThreadInternal { +// ---------------------------------------------------------------------------- +// wxCriticalSection implementation +// ---------------------------------------------------------------------------- +#define CRITICAL_SECTION ULONG +class wxCriticalSectionInternal +{ public: - // TODO + // init the critical section object + wxCriticalSectionInternal() + { //::InitializeCriticalSection(&m_data); + } + + // implicit cast to the associated data + operator CRITICAL_SECTION *() { return &m_data; } + + // free the associated ressources + ~wxCriticalSectionInternal() + { //::DeleteCriticalSection(&m_data); + } + +private: + CRITICAL_SECTION m_data; }; +wxCriticalSection::wxCriticalSection() +{ + m_critsect = new wxCriticalSectionInternal; +} + +wxCriticalSection::~wxCriticalSection() +{ + delete m_critsect; +} + +void wxCriticalSection::Enter() +{ +//TODO: ::EnterCriticalSection(*m_critsect); +} + +void wxCriticalSection::Leave() +{ +// TODO: ::LeaveCriticalSection(*m_critsect); +} + +// ---------------------------------------------------------------------------- +// wxThread implementation +// ---------------------------------------------------------------------------- + +// wxThreadInternal class +// ---------------------- + +class wxThreadInternal +{ +public: + wxThreadInternal() + { + m_hThread = 0; + m_state = STATE_NEW; + m_priority = 0; // TODO: WXTHREAD_DEFAULT_PRIORITY; + } + + // create a new (suspended) thread (for the given thread object) + bool Create(wxThread *thread); + + // suspend/resume/terminate + bool Suspend(); + bool Resume(); + void Cancel() { m_state = STATE_CANCELED; } + + // thread state + void SetState(wxThreadState state) { m_state = state; } + wxThreadState GetState() const { return m_state; } + + // thread priority + void SetPriority(unsigned int priority) { m_priority = priority; } + unsigned int GetPriority() const { return m_priority; } + + // thread handle and id + HANDLE GetHandle() const { return m_hThread; } + DWORD GetId() const { return m_tid; } + + // thread function + static DWORD OS2ThreadStart(wxThread *thread); + +private: + HANDLE m_hThread; // handle of the thread + wxThreadState m_state; // state, see wxThreadState enum + unsigned int m_priority; // thread priority in "wx" units + DWORD m_tid; // thread id +}; + +DWORD wxThreadInternal::OS2ThreadStart(wxThread *thread) +{ + // store the thread object in the TLS +// TODO: +/* + if ( !::TlsSetValue(s_tlsThisThread, thread) ) + { + wxLogSysError(_("Can not start thread: error writing TLS.")); + + return (DWORD)-1; + } +*/ + DWORD ret = (DWORD)thread->Entry(); + thread->p_internal->SetState(STATE_EXITED); + thread->OnExit(); + + delete thread; + + return ret; +} + +bool wxThreadInternal::Create(wxThread *thread) +{ +// TODO: +/* + m_hThread = ::CreateThread + ( + NULL, // default security + 0, // default stack size + (LPTHREAD_START_ROUTINE) // thread entry point + wxThreadInternal::OS2ThreadStart, // + (LPVOID)thread, // parameter + CREATE_SUSPENDED, // flags + &m_tid // [out] thread id + ); + + if ( m_hThread == NULL ) + { + wxLogSysError(_("Can't create thread")); + + return FALSE; + } + + // translate wxWindows priority to the Windows one + int win_priority; + if (m_priority <= 20) + win_priority = THREAD_PRIORITY_LOWEST; + else if (m_priority <= 40) + win_priority = THREAD_PRIORITY_BELOW_NORMAL; + else if (m_priority <= 60) + win_priority = THREAD_PRIORITY_NORMAL; + else if (m_priority <= 80) + win_priority = THREAD_PRIORITY_ABOVE_NORMAL; + else if (m_priority <= 100) + win_priority = THREAD_PRIORITY_HIGHEST; + else + { + wxFAIL_MSG(wxT("invalid value of thread priority parameter")); + win_priority = THREAD_PRIORITY_NORMAL; + } + + if ( ::SetThreadPriority(m_hThread, win_priority) == 0 ) + { + wxLogSysError(_("Can't set thread priority")); + } +*/ + return FALSE; +} + +bool wxThreadInternal::Suspend() +{ +// TODO: +/* + DWORD nSuspendCount = ::SuspendThread(m_hThread); + if ( nSuspendCount == (DWORD)-1 ) + { + wxLogSysError(_("Can not suspend thread %x"), m_hThread); + + return FALSE; + } + + m_state = STATE_PAUSED; +*/ + return FALSE; +} + +bool wxThreadInternal::Resume() +{ +// TODO: +/* + DWORD nSuspendCount = ::ResumeThread(m_hThread); + if ( nSuspendCount == (DWORD)-1 ) + { + wxLogSysError(_("Can not resume thread %x"), m_hThread); + + return FALSE; + } + + m_state = STATE_RUNNING; +*/ + return FALSE; +} + +// static functions +// ---------------- + +wxThread *wxThread::This() +{ + wxThread *thread = NULL; // TODO (wxThread *)::TlsGetValue(s_tlsThisThread); + +// TODO: +/* + // be careful, 0 may be a valid return value as well + if ( !thread && (::GetLastError() != NO_ERROR) ) + { + wxLogSysError(_("Couldn't get the current thread pointer")); + + // return NULL... + } +*/ + return thread; +} + +bool wxThread::IsMain() +{ +// TODO: return ::GetCurrentThreadId() == s_idMainThread; + return FALSE; +} + +#ifdef Yield + #undef Yield +#endif + +void wxThread::Yield() +{ + // 0 argument to Sleep() is special + ::DosSleep(0); +} + +void wxThread::Sleep(unsigned long milliseconds) +{ + ::DosSleep(milliseconds); +} + +// create/start thread +// ------------------- + wxThreadError wxThread::Create() { - // TODO + if ( !p_internal->Create(this) ) + return wxTHREAD_NO_RESOURCE; + return wxTHREAD_NO_ERROR; } -wxThreadError wxThread::Destroy() +wxThreadError wxThread::Run() { - // TODO - return wxTHREAD_NO_ERROR; + wxCriticalSectionLocker lock(m_critsect); + + if ( p_internal->GetState() != STATE_NEW ) + { + // actually, it may be almost any state at all, not only STATE_RUNNING + return wxTHREAD_RUNNING; + } + + return Resume(); } +// suspend/resume thread +// --------------------- + wxThreadError wxThread::Pause() { - // TODO - return wxTHREAD_NO_ERROR; + wxCriticalSectionLocker lock(m_critsect); + + return p_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR; } wxThreadError wxThread::Resume() { - // TODO - return wxTHREAD_NO_ERROR; -} + wxCriticalSectionLocker lock(m_critsect); -void wxThread::Exit(void *status) -{ - // TODO + return p_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR; } -void wxThread::SetPriority(int prio) +// stopping thread +// --------------- + +wxThread::ExitCode wxThread::Delete() { - // TODO + ExitCode rc = 0; + + // Delete() is always safe to call, so consider all possible states + if ( IsPaused() ) + Resume(); + + if ( IsRunning() ) + { + if ( IsMain() ) + { + // set flag for wxIsWaitingForThread() + s_waitingForThread = TRUE; + + wxBeginBusyCursor(); + } + + HANDLE hThread; + { + wxCriticalSectionLocker lock(m_critsect); + + p_internal->Cancel(); + hThread = p_internal->GetHandle(); + } + + // we can't just wait for the thread to terminate because it might be + // calling some GUI functions and so it will never terminate before we + // process the Windows messages that result from these functions + DWORD result; +// TODO: +/* + do + { + result = ::MsgWaitForMultipleObjects + ( + 1, // number of objects to wait for + &hThread, // the objects + FALSE, // don't wait for all objects + INFINITE, // no timeout + QS_ALLEVENTS // return as soon as there are any events + ); + + switch ( result ) + { + case 0xFFFFFFFF: + // error + wxLogSysError(_("Can not wait for thread termination")); + Kill(); + return (ExitCode)-1; + + case WAIT_OBJECT_0: + // thread we're waiting for terminated + break; + + case WAIT_OBJECT_0 + 1: + // new message arrived, process it + if ( !wxTheApp->DoMessage() ) + { + // WM_QUIT received: kill the thread + Kill(); + + return (ExitCode)-1; + } + + if ( IsMain() ) + { + // give the thread we're waiting for chance to exit + // from the GUI call it might have been in + if ( (s_nWaitingForGui > 0) && wxGuiOwnedByMainThread() ) + { + wxMutexGuiLeave(); + } + } + + break; + + default: + wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject")); + } + } while ( result != WAIT_OBJECT_0 ); +*/ + if ( IsMain() ) + { + s_waitingForThread = FALSE; + + wxEndBusyCursor(); + } + +// TODO: +/* + if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) ) + { + wxLogLastError("GetExitCodeThread"); + + rc = (ExitCode)-1; + } + + wxASSERT_MSG( (LPVOID)rc != (LPVOID)STILL_ACTIVE, + wxT("thread must be already terminated.") ); + + ::CloseHandle(hThread); +*/ + } + + return rc; } -int wxThread::GetPriority() const +wxThreadError wxThread::Kill() { - // TODO - return 0; + if ( !IsRunning() ) + return wxTHREAD_NOT_RUNNING; + +// TODO: +/* + if ( !::TerminateThread(p_internal->GetHandle(), (DWORD)-1) ) + { + wxLogSysError(_("Couldn't terminate thread")); + + return wxTHREAD_MISC_ERROR; + } +*/ + delete this; + + return wxTHREAD_NO_ERROR; } -void wxThread::DeferDestroy(bool on) +void wxThread::Exit(void *status) { - // TODO + delete this; + +// TODO: ::ExitThread((DWORD)status); + + wxFAIL_MSG(wxT("Couldn't return from ExitThread()!")); } -void wxThread::TestDestroy() +void wxThread::SetPriority(unsigned int prio) { - // TODO + wxCriticalSectionLocker lock(m_critsect); + + p_internal->SetPriority(prio); } -void *wxThread::Join() +unsigned int wxThread::GetPriority() const { - // TODO - return (void*) NULL; + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); + + return p_internal->GetPriority(); } unsigned long wxThread::GetID() const { - // TODO - return 0; + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); + + return (unsigned long)p_internal->GetId(); } -/* -wxThread *wxThread::GetThreadFromID(unsigned long id) +bool wxThread::IsRunning() const { - // TODO - return NULL; + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); + + return p_internal->GetState() == STATE_RUNNING; } -*/ bool wxThread::IsAlive() const { - // TODO - return FALSE; + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); + + return (p_internal->GetState() == STATE_RUNNING) || + (p_internal->GetState() == STATE_PAUSED); } -bool wxThread::IsRunning() const +bool wxThread::IsPaused() const { - // TODO - return FALSE; + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); + + return (p_internal->GetState() == STATE_PAUSED); } -bool wxThread::IsMain() +bool wxThread::TestDestroy() { - // TODO - return FALSE; + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); + + return p_internal->GetState() == STATE_CANCELED; } wxThread::wxThread() { p_internal = new wxThreadInternal(); - - // TODO } wxThread::~wxThread() { - Destroy(); - Join(); delete p_internal; } -// The default callback just joins the thread and throws away the result. -void wxThread::OnExit() -{ - Join(); -} +// ---------------------------------------------------------------------------- +// Automatic initialization for thread module +// ---------------------------------------------------------------------------- -// Automatic initialization -class wxThreadModule : public wxModule { - DECLARE_DYNAMIC_CLASS(wxThreadModule) +class wxThreadModule : public wxModule +{ public: - virtual bool OnInit() { - /* TODO p_mainid = GetCurrentThread(); */ - wxMainMutex = new wxMutex(); - wxMainMutex->Lock(); - return TRUE; - } + virtual bool OnInit(); + virtual void OnExit(); - // Global cleanup - virtual void OnExit() { - wxMainMutex->Unlock(); - delete wxMainMutex; - } +private: + DECLARE_DYNAMIC_CLASS(wxThreadModule) }; IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule) +bool wxThreadModule::OnInit() +{ + // allocate TLS index for storing the pointer to the current thread +// TODO: +/* + s_tlsThisThread = ::TlsAlloc(); + if ( s_tlsThisThread == 0xFFFFFFFF ) + { + // in normal circumstances it will only happen if all other + // TLS_MINIMUM_AVAILABLE (>= 64) indices are already taken - in other + // words, this should never happen + wxLogSysError(_("Thread module initialization failed: " + "impossible to allocate index in thread " + "local storage")); + + return FALSE; + } +*/ + // main thread doesn't have associated wxThread object, so store 0 in the + // TLS instead + +// TODO: +/* + if ( !::TlsSetValue(s_tlsThisThread, (LPVOID)0) ) + { + ::TlsFree(s_tlsThisThread); + s_tlsThisThread = 0xFFFFFFFF; + + wxLogSysError(_("Thread module initialization failed: " + "can not store value in thread local storage")); + + return FALSE; + } +*/ + s_critsectWaitingForGui = new wxCriticalSection(); + + s_critsectGui = new wxCriticalSection(); + s_critsectGui->Enter(); + + // no error return for GetCurrentThreadId() +// s_idMainThread = ::GetCurrentThreadId(); + + return TRUE; +} + +void wxThreadModule::OnExit() +{ +// TODO: +/* + if ( !::TlsFree(s_tlsThisThread) ) + { + wxLogLastError("TlsFree failed."); + } +*/ + if ( s_critsectGui ) + { + s_critsectGui->Leave(); + delete s_critsectGui; + s_critsectGui = NULL; + } + + wxDELETE(s_critsectWaitingForGui); +} + +// ---------------------------------------------------------------------------- +// under Windows, these functions are implemented usign a critical section and +// not a mutex, so the names are a bit confusing +// ---------------------------------------------------------------------------- + +void WXDLLEXPORT wxMutexGuiEnter() +{ + // this would dead lock everything... + wxASSERT_MSG( !wxThread::IsMain(), + wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); + + // the order in which we enter the critical sections here is crucial!! + + // set the flag telling to the main thread that we want to do some GUI + { + wxCriticalSectionLocker enter(*s_critsectWaitingForGui); + + s_nWaitingForGui++; + } + + wxWakeUpMainThread(); + + // now we may block here because the main thread will soon let us in + // (during the next iteration of OnIdle()) + s_critsectGui->Enter(); +} + +void WXDLLEXPORT wxMutexGuiLeave() +{ + wxCriticalSectionLocker enter(*s_critsectWaitingForGui); + + if ( wxThread::IsMain() ) + { + s_bGuiOwnedByMainThread = FALSE; + } + else + { + // decrement the number of waiters now + wxASSERT_MSG( s_nWaitingForGui > 0, + wxT("calling wxMutexGuiLeave() without entering it first?") ); + + s_nWaitingForGui--; + + wxWakeUpMainThread(); + } + + s_critsectGui->Leave(); +} + +void WXDLLEXPORT wxMutexGuiLeaveOrEnter() +{ + wxASSERT_MSG( wxThread::IsMain(), + wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); + + wxCriticalSectionLocker enter(*s_critsectWaitingForGui); + + if ( s_nWaitingForGui == 0 ) + { + // no threads are waiting for GUI - so we may acquire the lock without + // any danger (but only if we don't already have it) + if ( !wxGuiOwnedByMainThread() ) + { + s_critsectGui->Enter(); + + s_bGuiOwnedByMainThread = TRUE; + } + //else: already have it, nothing to do + } + else + { + // some threads are waiting, release the GUI lock if we have it + if ( wxGuiOwnedByMainThread() ) + { + wxMutexGuiLeave(); + } + //else: some other worker thread is doing GUI + } +} + +bool WXDLLEXPORT wxGuiOwnedByMainThread() +{ + return s_bGuiOwnedByMainThread; +} + +// wake up the main thread if it's in ::GetMessage() +void WXDLLEXPORT wxWakeUpMainThread() +{ + // sending any message would do - hopefully WM_NULL is harmless enough +// TODO: +/* + if ( !::PostThreadMessage(s_idMainThread, WM_NULL, 0, 0) ) + { + // should never happen + wxLogLastError("PostThreadMessage(WM_NULL)"); + } +*/ +} + +bool WXDLLEXPORT wxIsWaitingForThread() +{ + return s_waitingForThread; +} + + #endif // wxUSE_THREADS diff --git a/src/os2/timer.cpp b/src/os2/timer.cpp index 5262040cf6..bca6302c87 100644 --- a/src/os2/timer.cpp +++ b/src/os2/timer.cpp @@ -1,52 +1,134 @@ ///////////////////////////////////////////////////////////////////////////// // Name: timer.cpp // Purpose: wxTimer implementation -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "timer.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/list.h" + #include "wx/event.h" + #include "wx/app.h" #endif +#include "wx/intl.h" +#include "wx/log.h" + #include "wx/timer.h" +#include +#include + +#include + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +wxList wxTimerList(wxKEY_INTEGER); +UINT wxTimerProc(HWND hwnd, WORD, int idTimer, DWORD); + +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + #if !USE_SHARED_LIBRARY IMPLEMENT_ABSTRACT_CLASS(wxTimer, wxObject) #endif wxTimer::wxTimer() { - m_milli = 0 ; - m_id = 0; - m_oneShot = FALSE; + milli = 0 ; + id = 0; + oneShot = FALSE; } wxTimer::~wxTimer() { Stop(); + + wxTimerList.DeleteObject(this); } bool wxTimer::Start(int milliseconds,bool mode) { - m_oneShot = mode ; - if (milliseconds <= 0) - return FALSE; + oneShot = mode; + if (milliseconds < 0) + milliseconds = lastMilli; + + wxCHECK_MSG( milliseconds > 0, FALSE, wxT("invalid value for timer timeour") ); + + lastMilli = milli = milliseconds; + + wxTimerList.DeleteObject(this); +// TODO: +/* + TIMERPROC wxTimerProcInst = (TIMERPROC) + MakeProcInstance((FARPROC)wxTimerProc, wxGetInstance()); - m_milli = milliseconds; + id = SetTimer(NULL, (UINT)(id ? id : 1), + (UINT)milliseconds, wxTimerProcInst); +*/ + if (id > 0) + { + wxTimerList.Append(id, this); - // TODO: set the timer going. - return FALSE; + return TRUE; + } + else + { + wxLogSysError(_("Couldn't create a timer")); + + return FALSE; + } } void wxTimer::Stop() { - m_id = 0 ; - m_milli = 0 ; + if ( id ) + { +// KillTimer(NULL, (UINT)id); + wxTimerList.DeleteObject(this); + } + id = 0; + milli = 0; } +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +void wxProcessTimer(wxTimer& timer) +{ + // Avoid to process spurious timer events + if ( timer.id == 0) + return; + + if ( timer.oneShot ) + timer.Stop(); + + timer.Notify(); +} + +UINT wxTimerProc(HWND WXUNUSED(hwnd), WORD, int idTimer, DWORD) +{ + wxNode *node = wxTimerList.Find((long)idTimer); + + wxCHECK_MSG( node, 0, wxT("bogus timer id in wxTimerProc") ); + + wxProcessTimer(*(wxTimer *)node->Data()); + + return 0; +} diff --git a/src/os2/toolbar.cpp b/src/os2/toolbar.cpp index 3cb859e366..922a55e998 100644 --- a/src/os2/toolbar.cpp +++ b/src/os2/toolbar.cpp @@ -1,126 +1,493 @@ ///////////////////////////////////////////////////////////////////////////// // Name: toolbar.cpp // Purpose: wxToolBar -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: 04/01/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "toolbar.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" +#ifndef WX_PRECOMP #include "wx/wx.h" +#endif + +#if wxUSE_BUTTONBAR && wxUSE_TOOLBAR && defined(__WIN95__) + +#include "malloc.h" +#define INCL_PM +#include + #include "wx/toolbar.h" +#include "wx/app.h" +#include "wx/os2/private.h" + +// Styles +#ifndef TBSTYLE_FLAT +#define TBSTYLE_LIST 0x1000 +#define TBSTYLE_FLAT 0x0800 +#define TBSTYLE_TRANSPARENT 0x8000 +#endif + // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT + +// Messages +#ifndef TB_GETSTYLE +#define TB_GETSTYLE (WM_USER + 57) +#define TB_SETSTYLE (WM_USER + 56) +#endif + +/* Hint from a newsgroup for custom flatbar drawing: +Set the TBSTYLE_CUSTOMERASE style, then handle the +NM_CUSTOMDRAW message and do your custom drawing. +*/ + +#define DEFAULTBITMAPX 16 +#define DEFAULTBITMAPY 15 +#define DEFAULTBUTTONX 24 +#define DEFAULTBUTTONY 24 +#define DEFAULTBARHEIGHT 27 #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase) +#endif BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase) + EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent) + EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged) END_EVENT_TABLE() -#endif + +static void wxMapBitmap(HBITMAP hBitmap, int width, int height); wxToolBar::wxToolBar() { m_maxWidth = -1; m_maxHeight = -1; - m_defaultWidth = 24; - m_defaultHeight = 22; - // TODO + m_hBitmap = 0; + m_defaultWidth = DEFAULTBITMAPX; + m_defaultHeight = DEFAULTBITMAPY; } -bool wxToolBar::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, - long style, const wxString& name) +bool wxToolBar::Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) { - m_maxWidth = -1; - m_maxHeight = -1; - - m_defaultWidth = 24; - m_defaultHeight = 22; - SetName(name); + m_hWnd = 0; + m_backgroundColour = *wxWHITE; //TODO: wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), +// GetGValue(GetSysColor(COLOR_BTNFACE)), +// GetBValue(GetSysColor(COLOR_BTNFACE))); + m_foregroundColour = *wxBLACK ; - m_windowStyle = style; + wxASSERT_MSG( (style & wxTB_VERTICAL) == 0, + wxT("Sorry, wxToolBar under Windows 95 only " + "supports horizontal orientation.") ); - SetParent(parent); + m_maxWidth = -1; + m_maxHeight = -1; - if (parent) parent->AddChild(this); + m_hBitmap = 0; - // TODO create toolbar - - return FALSE; + m_defaultWidth = DEFAULTBITMAPX; + m_defaultHeight = DEFAULTBITMAPY; + SetName(name); + + m_windowStyle = style; + + SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); + SetParent(parent); + + int x = pos.x; + int y = pos.y; + int width = size.x; + int height = size.y; + + if (width <= 0) + width = 100; + if (height <= 0) + height = 30; + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + m_windowId = (id < 0 ? NewControlId() : id); + DWORD msflags = 0; +// TODO: +/* + if (style & wxBORDER) + msflags |= WS_BORDER; + msflags |= WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS; + + if (style & wxTB_FLAT) + { + if (wxTheApp->GetComCtl32Version() > 400) + msflags |= TBSTYLE_FLAT; + } + + bool want3D; + WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ; + + // Even with extended styles, need to combine with WS_BORDER + // for them to look right. + if ( want3D || wxStyleHasBorder(m_windowStyle) ) + msflags |= WS_BORDER; + + // Create the toolbar control. + HWND hWndToolbar = CreateWindowEx + ( + exStyle, // Extended styles. + TOOLBARCLASSNAME, // Class name for the toolbar. + wxT(""), // No default text. + msflags, // Styles + x, y, width, height, // Standard toolbar size and position. + (HWND) parent->GetHWND(), // Parent window of the toolbar. + (HMENU)m_windowId, // Toolbar ID. + wxGetInstance(), // Current instance. + NULL // No class data. + ); + + wxCHECK_MSG( hWndToolbar, FALSE, wxT("Toolbar creation failed") ); + + // Toolbar-specific initialisation + ::SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, + (WPARAM)sizeof(TBBUTTON), (LPARAM)0); +*/ + m_hWnd = (WXHWND) hWndToolbar; + if (parent) + parent->AddChild(this); + + SubclassWin((WXHWND)hWndToolbar); + + return TRUE; } wxToolBar::~wxToolBar() { - // TODO + UnsubclassWin(); + + if (m_hBitmap) + { +// ::DeleteObject((HBITMAP) m_hBitmap); + m_hBitmap = 0; + } } bool wxToolBar::CreateTools() { - if (m_tools.Number() == 0) + if (m_tools.Number() == 0) + return FALSE; + + HBITMAP oldToolBarBitmap = (HBITMAP) m_hBitmap; + + int totalBitmapWidth = (int)(m_defaultWidth * m_tools.Number()); + int totalBitmapHeight = (int)m_defaultHeight; + +// TODO: +/* + // Create a bitmap for all the tool bitmaps + HDC dc = ::GetDC(NULL); + m_hBitmap = (WXHBITMAP) ::CreateCompatibleBitmap(dc, totalBitmapWidth, totalBitmapHeight); + ::ReleaseDC(NULL, dc); + + // Now blit all the tools onto this bitmap + HDC memoryDC = ::CreateCompatibleDC(NULL); + HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, (HBITMAP) m_hBitmap); + + HDC memoryDC2 = ::CreateCompatibleDC(NULL); + int x = 0; + wxNode *node = m_tools.First(); + int noButtons = 0; + while (node) + { + wxToolBarTool *tool = (wxToolBarTool *)node->Data(); + if ((tool->m_toolStyle != wxTOOL_STYLE_SEPARATOR) && tool->m_bitmap1.Ok() && tool->m_bitmap1.GetHBITMAP()) + { +// wxPalette *palette = tool->m_bitmap1->GetPalette(); + + HBITMAP oldBitmap2 = (HBITMAP) ::SelectObject(memoryDC2, (HBITMAP) tool->m_bitmap1.GetHBITMAP()); + // int bltResult = + BitBlt(memoryDC, x, 0, (int) m_defaultWidth, (int) m_defaultHeight, memoryDC2, + 0, 0, SRCCOPY); + ::SelectObject(memoryDC2, oldBitmap2); + x += (int)m_defaultWidth; + noButtons ++; + } + node = node->Next(); + } + ::SelectObject(memoryDC, oldBitmap); + ::DeleteDC(memoryDC); + ::DeleteDC(memoryDC2); + + // Map to system colours + wxMapBitmap((HBITMAP) m_hBitmap, totalBitmapWidth, totalBitmapHeight); + + if ( oldToolBarBitmap ) + { + TBREPLACEBITMAP replaceBitmap; + replaceBitmap.hInstOld = NULL; + replaceBitmap.hInstNew = NULL; + replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; + replaceBitmap.nIDNew = (UINT) (HBITMAP) m_hBitmap; + replaceBitmap.nButtons = noButtons; + if (::SendMessage((HWND) GetHWND(), TB_REPLACEBITMAP, (WPARAM) 0, (LPARAM) &replaceBitmap) == -1) + { + wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); + } + + ::DeleteObject((HBITMAP) oldToolBarBitmap); + + // Now delete all the buttons + int i = 0; + while ( TRUE ) + { + // TODO: What about separators???? They don't have an id! + if ( ! ::SendMessage( (HWND) GetHWND(), TB_DELETEBUTTON, i, 0 ) ) + break; + } + } + else + { + TBADDBITMAP addBitmap; + addBitmap.hInst = 0; + addBitmap.nID = (UINT)m_hBitmap; + if (::SendMessage((HWND) GetHWND(), TB_ADDBITMAP, (WPARAM) noButtons, (LPARAM) &addBitmap) == -1) + { + wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); + } + } + + // Now add the buttons. + TBBUTTON buttons[50]; + + node = m_tools.First(); + int i = 0; + int bitmapId = 0; + while (node) + { + wxToolBarTool *tool = (wxToolBarTool *)node->Data(); + if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR) + { + buttons[i].iBitmap = 0; + buttons[i].idCommand = 0; + + buttons[i].fsState = TBSTATE_ENABLED; + buttons[i].fsStyle = TBSTYLE_SEP; + buttons[i].dwData = 0L; + buttons[i].iString = 0; + } + else + { + buttons[i].iBitmap = bitmapId; + buttons[i].idCommand = tool->m_index; + + buttons[i].fsState = 0; + if (tool->m_enabled) + buttons[i].fsState |= TBSTATE_ENABLED; + if (tool->m_toggleState) + buttons[i].fsState |= TBSTATE_CHECKED; + buttons[i].fsStyle = tool->m_isToggle ? TBSTYLE_CHECK : TBSTYLE_BUTTON; + buttons[i].dwData = 0L; + buttons[i].iString = 0; + + bitmapId ++; + } + + i ++; + node = node->Next(); + } + + long rc = ::SendMessage((HWND) GetHWND(), TB_ADDBUTTONS, (WPARAM)i, (LPARAM)& buttons); + + wxCHECK_MSG( rc, FALSE, wxT("failed to add buttons to the toolbar") ); + + (void)::SendMessage((HWND) GetHWND(), TB_AUTOSIZE, (WPARAM)0, (LPARAM) 0); + + SetRows(m_maxRows); +*/ + return TRUE; +} + +bool wxToolBar::OS2Command(WXUINT cmd, WXWORD id) +{ + wxNode *node = m_tools.Find((long)id); + if (!node) + return FALSE; + wxToolBarTool *tool = (wxToolBarTool *)node->Data(); +// TODO: +/* + if (tool->m_isToggle) + tool->m_toggleState = (1 == (1 & (int)::SendMessage((HWND) GetHWND(), TB_GETSTATE, (WPARAM) id, (LPARAM) 0))); + + BOOL ret = OnLeftClick((int)id, tool->m_toggleState); + if (ret == FALSE && tool->m_isToggle) + { + tool->m_toggleState = !tool->m_toggleState; + ::SendMessage((HWND) GetHWND(), TB_CHECKBUTTON, (WPARAM)id, (LPARAM)MAKELONG(tool->m_toggleState, 0)); + } + return TRUE; +*/ + return FALSE; +} + +bool wxToolBar::OS2OnNotify(int WXUNUSED(idCtrl), + WXLPARAM lParam, + WXLPARAM *result) +{ +// TODO: +/* + // First check if this applies to us + NMHDR *hdr = (NMHDR *)lParam; + + // the tooltips control created by the toolbar is sometimes Unicode, even in + // an ANSI application + int code = (int)hdr->code; + if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) ) + return FALSE; + + HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0); + if ( toolTipWnd != hdr->hwndFrom ) return FALSE; - // TODO + LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; + int id = (int)ttText->hdr.idFrom; + wxNode *node = m_tools.Find((long)id); + if (!node) + return FALSE; + + wxToolBarTool *tool = (wxToolBarTool *)node->Data(); + + const wxString& help = tool->m_shortHelpString; + + if ( !help.IsEmpty() ) + { + if ( code == TTN_NEEDTEXTA ) + { + ttText->lpszText = (wxChar *)help.c_str(); + } +#if (_WIN32_IE >= 0x0300) + else + { + // FIXME this is a temp hack only until I understand better what + // must be done in both ANSI and Unicode builds + + size_t lenAnsi = help.Len(); + #ifdef __MWERKS__ + // MetroWerks doesn't like calling mbstowcs with NULL argument + size_t lenUnicode = 2*lenAnsi; + #else + size_t lenUnicode = mbstowcs(NULL, help, lenAnsi); + #endif + + // using the pointer of right type avoids us doing all sorts of + // pointer arithmetics ourselves + wchar_t *dst = (wchar_t *)ttText->szText, + *pwz = new wchar_t[lenUnicode + 1]; + mbstowcs(pwz, help, lenAnsi + 1); + memcpy(dst, pwz, lenUnicode*sizeof(wchar_t)); + + // put the terminating _wide_ NUL + dst[lenUnicode] = 0; + + delete [] pwz; + } +#endif // _WIN32_IE >= 0x0300 + } + + // For backward compatibility... + OnMouseEnter(tool->m_index); + + return TRUE; +*/ return FALSE; } void wxToolBar::SetToolBitmapSize(const wxSize& size) { - m_defaultWidth = size.x; m_defaultHeight = size.y; - // TODO + m_defaultWidth = size.x; + m_defaultHeight = size.y; +// ::SendMessage((HWND) GetHWND(), TB_SETBITMAPSIZE, 0, (LPARAM) MAKELONG ((int)size.x, (int)size.y)); +} + +void wxToolBar::SetRows(int nRows) +{ +// TODO: +/* + RECT rect; + ::SendMessage((HWND) GetHWND(), TB_SETROWS, MAKEWPARAM(nRows, TRUE), (LPARAM) & rect); + m_maxWidth = (rect.right - rect.left + 2); + m_maxHeight = (rect.bottom - rect.top + 2); +*/ } wxSize wxToolBar::GetMaxSize() const { - // TODO - return wxSize(0, 0); +// TODO: +/* + if ((m_maxWidth == -1) || (m_maxHeight == -1)) + { + RECT rect; + ::SendMessage((HWND) GetHWND(), TB_SETROWS, MAKEWPARAM(m_maxRows, TRUE), (LPARAM) & rect); + ((wxToolBar *)this)->m_maxWidth = (rect.right - rect.left + 2); // ??? + ((wxToolBar *)this)->m_maxHeight = (rect.bottom - rect.top + 2); // ??? + } +*/ + return wxSize(m_maxWidth, m_maxHeight); } // The button size is bigger than the bitmap size wxSize wxToolBar::GetToolSize() const { - // TODO - return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); + return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); } void wxToolBar::EnableTool(int toolIndex, bool enable) { - wxNode *node = m_tools.Find((long)toolIndex); - if (node) - { - wxToolBarTool *tool = (wxToolBarTool *)node->Data(); - tool->m_enabled = enable; - // TODO enable button - } + wxNode *node = m_tools.Find((long)toolIndex); + if (node) + { + wxToolBarTool *tool = (wxToolBarTool *)node->Data(); + tool->m_enabled = enable; +// ::SendMessage((HWND) GetHWND(), TB_ENABLEBUTTON, (WPARAM)toolIndex, (LPARAM)MAKELONG(enable, 0)); + } } void wxToolBar::ToggleTool(int toolIndex, bool toggle) { - wxNode *node = m_tools.Find((long)toolIndex); - if (node) + wxNode *node = m_tools.Find((long)toolIndex); + if (node) + { + wxToolBarTool *tool = (wxToolBarTool *)node->Data(); + if (tool->m_isToggle) { - wxToolBarTool *tool = (wxToolBarTool *)node->Data(); - if (tool->m_isToggle) - { - tool->m_toggleState = toggle; - // TODO: set toggle state - } + tool->m_toggleState = toggle; +// ::SendMessage((HWND) GetHWND(), TB_CHECKBUTTON, (WPARAM)toolIndex, (LPARAM)MAKELONG(toggle, 0)); } + } +} + +bool wxToolBar::GetToolState(int toolIndex) const +{ +// return (::SendMessage((HWND) GetHWND(), TB_ISBUTTONCHECKED, (WPARAM)toolIndex, (LPARAM)0) != 0); + return FALSE; } void wxToolBar::ClearTools() { - // TODO - wxToolBarBase::ClearTools(); + // TODO: Don't know how to reset the toolbar bitmap, as yet. + // But adding tools and calling CreateTools should probably + // recreate a buttonbar OK. + wxToolBarBase::ClearTools(); } // If pushedBitmap is NULL, a reversed version of bitmap is // created and used as the pushed/toggled image. // If toggle is TRUE, the button toggles between the two states. - wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap, bool toggle, long xPos, long yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2) { @@ -137,9 +504,137 @@ wxToolBarTool *wxToolBar::AddTool(int index, const wxBitmap& bitmap, const wxBit else tool->m_y = m_yMargin; - tool->SetSize(GetDefaultButtonWidth(), GetDefaultButtonHeight()); + tool->SetSize(GetToolSize().x, GetToolSize().y); m_tools.Append((long)index, tool); return tool; } +// Responds to colour changes, and passes event on to children. +void wxToolBar::OnSysColourChanged(wxSysColourChangedEvent& event) +{ +// TODO: +/* + m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), + GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE))); +*/ + // Remap the buttons + CreateTools(); + + Refresh(); + + // Propagate the event to the non-top-level children + wxWindow::OnSysColourChanged(event); +} + +void wxToolBar::OnMouseEvent(wxMouseEvent& event) +{ + if (event.RightDown()) + { + // For now, we don't have an id. Later we could + // try finding the tool. + OnRightClick((int)-1, event.GetX(), event.GetY()); + } + else + { + event.Skip(); + } +} + +// These are the default colors used to map the bitmap colors +// to the current system colors + +#define BGR_BUTTONTEXT (RGB(000,000,000)) // black +#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey +#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey +#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white +#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue +#define BGR_BACKGROUND (RGB(255,000,255)) // magenta + +void wxMapBitmap(HBITMAP hBitmap, int width, int height) +{ + COLORMAP ColorMap[] = { + {BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black + {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey + {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey + {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white + {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue + {BGR_BACKGROUND, COLOR_WINDOW} // magenta + }; + + int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP)); + int n; + for ( n = 0; n < NUM_MAPS; n++) + { + ColorMap[n].to = ::GetSysColor(ColorMap[n].to); + } + + HBITMAP hbmOld; + HDC hdcMem = CreateCompatibleDC(NULL); + + if (hdcMem) + { + hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap); + + int i, j, k; + for ( i = 0; i < width; i++) + { + for ( j = 0; j < height; j++) + { +// COLORREF pixel = ::GetPixel(hdcMem, i, j); +/* + BYTE red = GetRValue(pixel); + BYTE green = GetGValue(pixel); + BYTE blue = GetBValue(pixel); +*/ + + for ( k = 0; k < NUM_MAPS; k ++) + { + if ( ColorMap[k].from == pixel ) + { +// /* COLORREF actualPixel = */ ::SetPixel(hdcMem, i, j, ColorMap[k].to); + break; + } + } + } + } + + +// SelectObject(hdcMem, hbmOld); +// DeleteObject(hdcMem); + } + +} + +// Some experiments... +#if 0 + // What we want to do is create another bitmap which has a depth of 4, + // and set the bits. So probably we want to convert this HBITMAP into a + // DIB, then call SetDIBits. + // AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of + // the screen), then SetDIBits fails. + HBITMAP newBitmap = ::CreateBitmap(totalBitmapWidth, totalBitmapHeight, 1, 4, NULL); + HANDLE newDIB = ::BitmapToDIB((HBITMAP) m_hBitmap, NULL); + LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) GlobalLock(newDIB); + + dc = ::GetDC(NULL); +// LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB; + + int result = ::SetDIBits(dc, newBitmap, 0, lpbmi->biHeight, FindDIBBits((LPSTR)lpbmi), (LPBITMAPINFO)lpbmi, + DIB_PAL_COLORS); + DWORD err = GetLastError(); + + ::ReleaseDC(NULL, dc); + + // Delete the DIB + GlobalUnlock (newDIB); + GlobalFree (newDIB); + +// WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap); + // Substitute our new bitmap for the old one + ::DeleteObject((HBITMAP) m_hBitmap); + m_hBitmap = (WXHBITMAP) newBitmap; +#endif + + +#endif diff --git a/src/os2/tooltip.cpp b/src/os2/tooltip.cpp new file mode 100644 index 0000000000..224f1b3f0c --- /dev/null +++ b/src/os2/tooltip.cpp @@ -0,0 +1,214 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: msw/tooltip.cpp +// Purpose: wxToolTip class implementation for MSW +// Author: David Webster +// Modified by: +// Created: 10/17/99 +// RCS-ID: $Id$ +// Copyright: (c) David Webster +// Licence: wxWindows license +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP + #include "wx/wx.h" +#endif + +#if wxUSE_TOOLTIPS + +#include "wx/tooltip.h" +#include "wx/os2/private.h" + +// ---------------------------------------------------------------------------- +// global variables +// ---------------------------------------------------------------------------- + +// the tooltip parent window +WXHWND wxToolTip::hwndTT = (WXHWND)NULL; + +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- + + +// a simple wrapper around TOOLINFO Win32 structure +class wxToolInfo // define a TOOLINFO for OS/2 here : public TOOLINFO +{ +public: + wxToolInfo(wxWindow *win) + { + // initialize all members +// ::ZeroMemory(this, sizeof(TOOLINFO)); + + cbSize = sizeof(this); + uFlags = 0; // TTF_IDISHWND; + uId = (UINT)win->GetHWND(); + } + size_t cbSize; + ULONG uFlags; + UINT uId; + HWND hwnd; + char* lpszText; +}; + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +// send a message to the tooltip control +inline MRESULT SendTooltipMessage(WXHWND hwnd, + UINT msg, + MPARAM wParam, + MPARAM lParam) +{ +// return hwnd ? ::SendMessage((HWND)hwnd, msg, wParam, (MPARAM)lParam) +// : 0; + return (MRESULT)0; +} + +// send a message to all existing tooltip controls +static void SendTooltipMessageToAll(WXHWND hwnd, + UINT msg, + MPARAM wParam, + MPARAM lParam) +{ + if ( hwnd ) + (void)SendTooltipMessage((WXHWND)hwnd, msg, wParam, lParam); +} + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// static functions +// ---------------------------------------------------------------------------- + +void wxToolTip::Enable(bool flag) +{ +// SendTooltipMessageToAll((WXHWND)hwndTT,TTM_ACTIVATE, flag, 0); +} + +void wxToolTip::SetDelay(long milliseconds) +{ +// SendTooltipMessageToAll((WXHWND)hwndTT,TTM_SETDELAYTIME, TTDT_INITIAL, milliseconds); +} + +// --------------------------------------------------------------------------- +// implementation helpers +// --------------------------------------------------------------------------- + +// create the tooltip ctrl for our parent frame if it doesn't exist yet +WXHWND wxToolTip::GetToolTipCtrl() +{ +// TODO: +/* + if ( !hwndTT ) + { + hwndTT = (WXHWND)::CreateWindow(TOOLTIPS_CLASS, + (LPSTR)NULL, + TTS_ALWAYSTIP, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + NULL, (HMENU)NULL, + wxGetInstance(), + NULL); + if ( hwndTT ) + { + SetWindowPos((HWND)hwndTT, HWND_TOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + + } + return (WXHWND)hwndTT; +*/ + return (WXHWND)0; +} + +void wxToolTip::RelayEvent(WXMSG *msg) +{ +// (void)SendTooltipMessage(GetToolTipCtrl(), TTM_RELAYEVENT, 0, msg); +} + +// ---------------------------------------------------------------------------- +// ctor & dtor +// ---------------------------------------------------------------------------- + +wxToolTip::wxToolTip(const wxString &tip) + : m_text(tip) +{ + m_window = NULL; +} + +wxToolTip::~wxToolTip() +{ + // there is no need to Remove() this tool - it will be done automatically + // anyhow +} + +// ---------------------------------------------------------------------------- +// others +// ---------------------------------------------------------------------------- + +void wxToolTip::Remove() +{ + // remove this tool from the tooltip control + if ( m_window ) + { + wxToolInfo ti(m_window); +// (void)SendTooltipMessage(GetToolTipCtrl(), TTM_DELTOOL, 0, &ti); + } +} + +void wxToolTip::SetWindow(wxWindow *win) +{ + Remove(); + + m_window = win; + + if ( m_window ) + { + wxToolInfo ti(m_window); + + // as we store our text anyhow, it seems useless to waste system memory + // by asking the tooltip ctrl to remember it too - instead it will send + // us TTN_NEEDTEXT (via WM_NOTIFY) when it is about to be shown + ti.hwnd = (HWND)m_window->GetHWND(); +// ti.lpszText = LPSTR_TEXTCALLBACK; + // instead of: ti.lpszText = (char *)m_text.c_str(); + +// TODO: +/* + if ( !SendTooltipMessage(GetToolTipCtrl(), TTM_ADDTOOL, 0, &ti) ) + { + wxLogSysError(_("Failed to create the tooltip '%s'"), + m_text.c_str()); + } +*/ + } +} + +void wxToolTip::SetTip(const wxString& tip) +{ + m_text = tip; + + if ( m_window ) + { + // update it immediately + wxToolInfo ti(m_window); + ti.lpszText = (wxChar *)m_text.c_str(); + +// (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, 0, &ti); + } +} + +#endif // wxUSE_TOOLTIPS diff --git a/src/os2/treectrl.cpp b/src/os2/treectrl.cpp index 137a885dbf..8671b38c71 100644 --- a/src/os2/treectrl.cpp +++ b/src/os2/treectrl.cpp @@ -1,418 +1,1689 @@ ///////////////////////////////////////////////////////////////////////////// // Name: treectrl.cpp // Purpose: wxTreeCtrl. See also Robert's generic wxTreeCtrl. -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "treectrl.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#include "wx/window.h" +#include "wx/os2/private.h" + +#include "wx/log.h" +#include "wx/dynarray.h" +#include "wx/imaglist.h" +#include "wx/treectrl.h" +#include "wx/settings.h" + +// Bug in headers, sometimes +#ifndef TVIS_FOCUSED + #define TVIS_FOCUSED 0x0001 #endif -#include "wx/stubs/textctrl.h" -#include "wx/stubs/treectrl.h" +// ---------------------------------------------------------------------------- +// private classes +// ---------------------------------------------------------------------------- -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl) -IMPLEMENT_DYNAMIC_CLASS(wxTreeItem, wxObject) +struct wxTreeViewItem// ??? : public TV_ITEM +{ + wxTreeViewItem(const wxTreeItemId& item, // the item handle + UINT mask_, // fields which are valid + UINT stateMask_ = 0) // for TVIF_STATE only + { + // hItem member is always valid + mask = mask_; // | TVIF_HANDLE; + stateMask = stateMask_; + hItem = /*(HTREEITEM)*/ (WXHTREEITEM) item; + } + // OS/2 subs + UINT mask; + UINT stateMask; + WXHTREEITEM hItem; +}; + +// a class which encapsulates the tree traversal logic: it vists all (unless +// OnVisit() returns FALSE) items under the given one +class wxTreeTraversal +{ +public: + wxTreeTraversal(const wxTreeCtrl *tree) + { + m_tree = tree; + } + + // do traverse the tree: visit all items (recursively by default) under the + // given one; return TRUE if all items were traversed or FALSE if the + // traversal was aborted because OnVisit returned FALSE + bool DoTraverse(const wxTreeItemId& root, bool recursively = TRUE); + + // override this function to do whatever is needed for each item, return + // FALSE to stop traversing + virtual bool OnVisit(const wxTreeItemId& item) = 0; + +protected: + const wxTreeCtrl *GetTree() const { return m_tree; } + +private: + bool Traverse(const wxTreeItemId& root, bool recursively); + + const wxTreeCtrl *m_tree; +}; + +// internal class for getting the selected items +class TraverseSelections : public wxTreeTraversal +{ +public: + TraverseSelections(const wxTreeCtrl *tree, + wxArrayTreeItemIds& selections) + : wxTreeTraversal(tree), m_selections(selections) + { + m_selections.Empty(); + + DoTraverse(tree->GetRootItem()); + } + + virtual bool OnVisit(const wxTreeItemId& item) + { + if ( GetTree()->IsItemChecked(item) ) + { + m_selections.Add(item); + } + + return TRUE; + } +private: + wxArrayTreeItemIds& m_selections; +}; + +// internal class for counting tree items +class TraverseCounter : public wxTreeTraversal +{ +public: + TraverseCounter(const wxTreeCtrl *tree, + const wxTreeItemId& root, + bool recursively) + : wxTreeTraversal(tree) + { + m_count = 0; + + DoTraverse(root, recursively); + } + + virtual bool OnVisit(const wxTreeItemId& item) + { + m_count++; + + return TRUE; + } + + size_t GetCount() const { return m_count; } + +private: + size_t m_count; +}; + +// ---------------------------------------------------------------------------- +// This class is needed for support of different images: the Win32 common +// control natively supports only 2 images (the normal one and another for the +// selected state). We wish to provide support for 2 more of them for folder +// items (i.e. those which have children): for expanded state and for expanded +// selected state. For this we use this structure to store the additional items +// images. +// +// There is only one problem with this: when we retrieve the item's data, we +// don't know whether we get a pointer to wxTreeItemData or +// wxTreeItemIndirectData. So we have to maintain a list of all items which +// have indirect data inside the listctrl itself. +// ---------------------------------------------------------------------------- +class wxTreeItemIndirectData +{ +public: + // ctor associates this data with the item and the real item data becomes + // available through our GetData() method + wxTreeItemIndirectData(wxTreeCtrl *tree, const wxTreeItemId& item) + { + for ( size_t n = 0; n < WXSIZEOF(m_images); n++ ) + { + m_images[n] = -1; + } + + // save the old data + m_data = tree->GetItemData(item); + + // and set ourselves as the new one + tree->SetIndirectItemData(item, this); + } + + // dtor deletes the associated data as well + ~wxTreeItemIndirectData() { delete m_data; } + + // accessors + // get the real data associated with the item + wxTreeItemData *GetData() const { return m_data; } + // change it + void SetData(wxTreeItemData *data) { m_data = data; } + + // do we have such image? + bool HasImage(wxTreeItemIcon which) const { return m_images[which] != -1; } + // get image + int GetImage(wxTreeItemIcon which) const { return m_images[which]; } + // change it + void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; } + +private: + // all the images associated with the item + int m_images[wxTreeItemIcon_Max]; + + wxTreeItemData *m_data; +}; + +// ---------------------------------------------------------------------------- +// macros +// ---------------------------------------------------------------------------- + +#if !USE_SHARED_LIBRARY + IMPLEMENT_DYNAMIC_CLASS(wxTreeCtrl, wxControl) #endif -wxTreeCtrl::wxTreeCtrl() +// ---------------------------------------------------------------------------- +// variables +// ---------------------------------------------------------------------------- + +// handy table for sending events +static const wxEventType g_events[2][2] = { - m_imageListNormal = NULL; - m_imageListState = NULL; - m_textCtrl = NULL; + { wxEVT_COMMAND_TREE_ITEM_COLLAPSED, wxEVT_COMMAND_TREE_ITEM_COLLAPSING }, + { wxEVT_COMMAND_TREE_ITEM_EXPANDED, wxEVT_COMMAND_TREE_ITEM_EXPANDING } +}; + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// tree traversal +// ---------------------------------------------------------------------------- + +bool wxTreeTraversal::DoTraverse(const wxTreeItemId& root, bool recursively) +{ + if ( !OnVisit(root) ) + return FALSE; + + return Traverse(root, recursively); } -bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, - long style, const wxValidator& validator, const wxString& name) +bool wxTreeTraversal::Traverse(const wxTreeItemId& root, bool recursively) { - SetName(name); - SetValidator(validator); + long cookie; + wxTreeItemId child = m_tree->GetFirstChild(root, cookie); + while ( child.IsOk() ) + { + // depth first traversal + if ( recursively && !Traverse(child, TRUE) ) + return FALSE; + + if ( !OnVisit(child) ) + return FALSE; + + child = m_tree->GetNextChild(root, cookie); + } + return TRUE; +} + +// ---------------------------------------------------------------------------- +// construction and destruction +// ---------------------------------------------------------------------------- + +void wxTreeCtrl::Init() +{ m_imageListNormal = NULL; m_imageListState = NULL; m_textCtrl = NULL; +} - m_windowStyle = style; +bool wxTreeCtrl::Create(wxWindow *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) +{ + Init(); + + if ( !CreateControl(parent, id, pos, size, style, validator, name) ) + return FALSE; +// TODO: +/* + DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP | + TVS_HASLINES | TVS_SHOWSELALWAYS; + + if ( m_windowStyle & wxTR_HAS_BUTTONS ) + wstyle |= TVS_HASBUTTONS; + + if ( m_windowStyle & wxTR_EDIT_LABELS ) + wstyle |= TVS_EDITLABELS; + + if ( m_windowStyle & wxTR_LINES_AT_ROOT ) + wstyle |= TVS_LINESATROOT; + + if ( m_windowStyle & wxTR_MULTIPLE ) + wstyle |= TVS_CHECKBOXES; + + // Create the tree control. + if ( !OS2CreateControl(WC_TREEVIEW, wstyle) ) + return FALSE; +*/ + SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + SetForegroundColour(wxWindow::GetParent()->GetForegroundColour()); + + // VZ: this is some experimental code which may be used to get the + // TVS_CHECKBOXES style functionality for comctl32.dll < 4.71. + // AFAIK, the standard DLL does about the same thing anyhow. +#if 0 + if ( m_windowStyle & wxTR_MULTIPLE ) + { + wxBitmap bmp; + + // create the DC compatible with the current screen + HDC hdcMem = CreateCompatibleDC(NULL); + + // create a mono bitmap of the standard size + int x = GetSystemMetrics(SM_CXMENUCHECK); + int y = GetSystemMetrics(SM_CYMENUCHECK); + wxImageList imagelistCheckboxes(x, y, FALSE, 2); + HBITMAP hbmpCheck = CreateBitmap(x, y, // bitmap size + 1, // # of color planes + 1, // # bits needed for one pixel + 0); // array containing colour data + SelectObject(hdcMem, hbmpCheck); + + // then draw a check mark into it + RECT rect = { 0, 0, x, y }; + if ( !::DrawFrameControl(hdcMem, &rect, + DFC_BUTTON, + DFCS_BUTTONCHECK | DFCS_CHECKED) ) + { + wxLogLastError(wxT("DrawFrameControl(check)")); + } + + bmp.SetHBITMAP((WXHBITMAP)hbmpCheck); + imagelistCheckboxes.Add(bmp); + + if ( !::DrawFrameControl(hdcMem, &rect, + DFC_BUTTON, + DFCS_BUTTONCHECK) ) + { + wxLogLastError(wxT("DrawFrameControl(uncheck)")); + } + + bmp.SetHBITMAP((WXHBITMAP)hbmpCheck); + imagelistCheckboxes.Add(bmp); + + // clean up + ::DeleteDC(hdcMem); + + // set the imagelist + SetStateImageList(&imagelistCheckboxes); + } +#endif // 0 - SetParent(parent); + SetSize(pos.x, pos.y, size.x, size.y); - m_windowId = (id == -1) ? NewControlId() : id; + return TRUE; +} - if (parent) parent->AddChild(this); +wxTreeCtrl::~wxTreeCtrl() +{ + DeleteTextCtrl(); - // TODO create tree control + // delete user data to prevent memory leaks +// DeleteAllItems(); +} - return FALSE; +// ---------------------------------------------------------------------------- +// accessors +// ---------------------------------------------------------------------------- + +// simple wrappers which add error checking in debug mode + +bool wxTreeCtrl::DoGetItem(wxTreeViewItem* tvItem) const +{ +// TODO: +/* + if ( !TreeView_GetItem(GetHwnd(), tvItem) ) + { + wxLogLastError("TreeView_GetItem"); + + return FALSE; + } +*/ + return TRUE; } -wxTreeCtrl::~wxTreeCtrl() +void wxTreeCtrl::DoSetItem(wxTreeViewItem* tvItem) { - if (m_textCtrl) +// TODO: +/* + if ( TreeView_SetItem(GetHwnd(), tvItem) == -1 ) { - delete m_textCtrl; + wxLogLastError("TreeView_SetItem"); } +*/ } -// Attributes -int wxTreeCtrl::GetCount() const +size_t wxTreeCtrl::GetCount() const { - // TODO +// return (size_t)TreeView_GetCount(GetHwnd()); return 0; } -int wxTreeCtrl::GetIndent() const +unsigned int wxTreeCtrl::GetIndent() const { - // TODO +// return TreeView_GetIndent(GetHwnd()); return 0; } -void wxTreeCtrl::SetIndent(int indent) +void wxTreeCtrl::SetIndent(unsigned int indent) { - // TODO +// TreeView_SetIndent(GetHwnd(), indent); } -wxImageList *wxTreeCtrl::GetImageList(int which) const +wxImageList *wxTreeCtrl::GetImageList() const { - if ( which == wxIMAGE_LIST_NORMAL ) - { return m_imageListNormal; - } - else if ( which == wxIMAGE_LIST_STATE ) +} + +wxImageList *wxTreeCtrl::GetStateImageList() const +{ + return m_imageListNormal; +} + +void wxTreeCtrl::SetAnyImageList(wxImageList *imageList, int which) +{ + // no error return +// TODO: +/* + TreeView_SetImageList(GetHwnd(), + imageList ? imageList->GetHIMAGELIST() : 0, + which); +*/ +} + +void wxTreeCtrl::SetImageList(wxImageList *imageList) +{ +// SetAnyImageList(m_imageListNormal = imageList, TVSIL_NORMAL); +} + +void wxTreeCtrl::SetStateImageList(wxImageList *imageList) +{ +// SetAnyImageList(m_imageListState = imageList, TVSIL_STATE); +} + +size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, + bool recursively) const +{ + TraverseCounter counter(this, item, recursively); + + return counter.GetCount() - 1; +} + +// ---------------------------------------------------------------------------- +// Item access +// ---------------------------------------------------------------------------- + +wxString wxTreeCtrl::GetItemText(const wxTreeItemId& item) const +{ + wxChar buf[512]; // the size is arbitrary... +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_TEXT); + tvItem.pszText = buf; + tvItem.cchTextMax = WXSIZEOF(buf); + if ( !DoGetItem(&tvItem) ) { - return m_imageListState; - } - return NULL; + // don't return some garbage which was on stack, but an empty string + buf[0] = wxT('\0'); + } +*/ + return wxString(buf); +} + +void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text) +{ +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_TEXT); + tvItem.pszText = (wxChar *)text.c_str(); // conversion is ok + DoSetItem(&tvItem); +*/ } -void wxTreeCtrl::SetImageList(wxImageList *imageList, int which) +int wxTreeCtrl::DoGetItemImageFromData(const wxTreeItemId& item, + wxTreeItemIcon which) const { - if ( which == wxIMAGE_LIST_NORMAL ) +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_PARAM); + if ( !DoGetItem(&tvItem) ) { - m_imageListNormal = imageList; + return -1; } - else if ( which == wxIMAGE_LIST_STATE ) + return ((wxTreeItemIndirectData *)tvItem.lParam)->GetImage(which); +*/ + return -1; +} + +void wxTreeCtrl::DoSetItemImageFromData(const wxTreeItemId& item, + int image, + wxTreeItemIcon which) const +{ +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_PARAM); + if ( !DoGetItem(&tvItem) ) { - m_imageListState = imageList; + return; } - // TODO + + wxTreeItemIndirectData *data = ((wxTreeItemIndirectData *)tvItem.lParam); + + data->SetImage(image, which); + + // make sure that we have selected images as well + if ( which == wxTreeItemIcon_Normal && + !data->HasImage(wxTreeItemIcon_Selected) ) + { + data->SetImage(image, wxTreeItemIcon_Selected); + } + + if ( which == wxTreeItemIcon_Expanded && + !data->HasImage(wxTreeItemIcon_SelectedExpanded) ) + { + data->SetImage(image, wxTreeItemIcon_SelectedExpanded); + } +*/ } -long wxTreeCtrl::GetNextItem(long item, int code) const +void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item, + int image, + int imageSel) { - // TODO - return 0; +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_IMAGE | TVIF_SELECTEDIMAGE); + tvItem.iSelectedImage = imageSel; + tvItem.iImage = image; + DoSetItem(&tvItem); +*/ } -bool wxTreeCtrl::ItemHasChildren(long item) const +int wxTreeCtrl::GetItemImage(const wxTreeItemId& item, + wxTreeItemIcon which) const { - // TODO + if ( HasIndirectData(item) ) + { + return DoGetItemImageFromData(item, which); + } + + UINT mask; + switch ( which ) + { + default: + wxFAIL_MSG( wxT("unknown tree item image type") ); + + case wxTreeItemIcon_Normal: +// mask = TVIF_IMAGE; + break; + + case wxTreeItemIcon_Selected: +// mask = TVIF_SELECTEDIMAGE; + break; + + case wxTreeItemIcon_Expanded: + case wxTreeItemIcon_SelectedExpanded: + return -1; + } + + wxTreeViewItem tvItem(item, mask); + DoGetItem(&tvItem); + +// return mask == TVIF_IMAGE ? tvItem.iImage : tvItem.iSelectedImage; return FALSE; } -long wxTreeCtrl::GetChild(long item) const +void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image, + wxTreeItemIcon which) { - // TODO - return 0; + int imageNormal, imageSel; + switch ( which ) + { + default: + wxFAIL_MSG( wxT("unknown tree item image type") ); + + case wxTreeItemIcon_Normal: + imageNormal = image; + imageSel = GetItemSelectedImage(item); + break; + + case wxTreeItemIcon_Selected: + imageNormal = GetItemImage(item); + imageSel = image; + break; + + case wxTreeItemIcon_Expanded: + case wxTreeItemIcon_SelectedExpanded: + if ( !HasIndirectData(item) ) + { + // we need to get the old images first, because after we create + // the wxTreeItemIndirectData GetItemXXXImage() will use it to + // get the images + imageNormal = GetItemImage(item); + imageSel = GetItemSelectedImage(item); + + // if it doesn't have it yet, add it + wxTreeItemIndirectData *data = new + wxTreeItemIndirectData(this, item); + + // copy the data to the new location + data->SetImage(imageNormal, wxTreeItemIcon_Normal); + data->SetImage(imageSel, wxTreeItemIcon_Selected); + } + + DoSetItemImageFromData(item, image, which); + + // reset the normal/selected images because we won't use them any + // more - now they're stored inside the indirect data +// imageSel = I_IMAGECALLBACK; + break; + } + + // NB: at least in version 5.00.0518.9 of comctl32.dll we need to always + // change both normal and selected image - otherwise the change simply + // doesn't take place! + DoSetItemImages(item, imageNormal, imageSel); } -long wxTreeCtrl::GetParent(long item) const +wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const { - // TODO +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_PARAM); + if ( !DoGetItem(&tvItem) ) + { + return NULL; + } + + if ( HasIndirectData(item) ) + { + return ((wxTreeItemIndirectData *)tvItem.lParam)->GetData(); + } + else + { + return (wxTreeItemData *)tvItem.lParam; + } +*/ return 0; } -long wxTreeCtrl::GetFirstVisibleItem() const +void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data) { - // TODO - return 0; +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_PARAM); + + if ( HasIndirectData(item) ) + { + if ( DoGetItem(&tvItem) ) + { + ((wxTreeItemIndirectData *)tvItem.lParam)->SetData(data); + } + else + { + wxFAIL_MSG( wxT("failed to change tree items data") ); + } + } + else + { + tvItem.lParam = (MPARAM)data; + DoSetItem(&tvItem); + } +*/ } -long wxTreeCtrl::GetNextVisibleItem(long item) const +void wxTreeCtrl::SetIndirectItemData(const wxTreeItemId& item, + wxTreeItemIndirectData *data) { - // TODO - return 0; + // this should never happen because it's unnecessary and will probably lead + // to crash too because the code elsewhere supposes that the pointer the + // wxTreeItemIndirectData has is a real wxItemData and not + // wxTreeItemIndirectData as well + wxASSERT_MSG( !HasIndirectData(item), wxT("setting indirect data twice?") ); + + SetItemData(item, (wxTreeItemData *)data); + + m_itemsWithIndirectData.Add(item); } -long wxTreeCtrl::GetSelection() const +bool wxTreeCtrl::HasIndirectData(const wxTreeItemId& item) const { - // TODO - return 0; + return m_itemsWithIndirectData.Index(item) != wxNOT_FOUND; } -long wxTreeCtrl::GetRootItem() const +void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) { - // TODO - return 0; +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_CHILDREN); + tvItem.cChildren = (int)has; + DoSetItem(&tvItem); +*/ +} + +void wxTreeCtrl::SetItemBold(const wxTreeItemId& item, bool bold) +{ +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_BOLD); + tvItem.state = bold ? TVIS_BOLD : 0; + DoSetItem(&tvItem); +*/ +} + +void wxTreeCtrl::SetItemDropHighlight(const wxTreeItemId& item, bool highlight) +{ +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_DROPHILITED); + tvItem.state = highlight ? TVIS_DROPHILITED : 0; + DoSetItem(&tvItem); +*/ } -bool wxTreeCtrl::GetItem(wxTreeItem& info) const +// ---------------------------------------------------------------------------- +// Item status +// ---------------------------------------------------------------------------- + +bool wxTreeCtrl::IsVisible(const wxTreeItemId& item) const { - // TODO + // Bug in Gnu-Win32 headers, so don't use the macro TreeView_GetItemRect +// TODO: +/* + RECT rect; + return SendMessage(GetHwnd(), TVM_GETITEMRECT, FALSE, (LPARAM)&rect) != 0; +*/ return FALSE; } -bool wxTreeCtrl::SetItem(wxTreeItem& info) +bool wxTreeCtrl::ItemHasChildren(const wxTreeItemId& item) const { - // TODO +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_CHILDREN); + DoGetItem(&tvItem); + + return tvItem.cChildren != 0; +*/ return FALSE; } -int wxTreeCtrl::GetItemState(long item, long stateMask) const +bool wxTreeCtrl::IsExpanded(const wxTreeItemId& item) const { - wxTreeItem info; + // probably not a good idea to put it here + //wxASSERT( ItemHasChildren(item) ); - info.m_mask = wxTREE_MASK_STATE ; - info.m_stateMask = stateMask; - info.m_itemId = item; +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_EXPANDED); + DoGetItem(&tvItem); - if (!GetItem(info)) - return 0; + return (tvItem.state & TVIS_EXPANDED) != 0; +*/ + return FALSE; +} - return info.m_state; +bool wxTreeCtrl::IsSelected(const wxTreeItemId& item) const +{ +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_SELECTED); + DoGetItem(&tvItem); + + return (tvItem.state & TVIS_SELECTED) != 0; +*/ + return FALSE; } -bool wxTreeCtrl::SetItemState(long item, long state, long stateMask) +bool wxTreeCtrl::IsBold(const wxTreeItemId& item) const { - wxTreeItem info; +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_BOLD); + DoGetItem(&tvItem); - info.m_mask = wxTREE_MASK_STATE ; - info.m_state = state; - info.m_stateMask = stateMask; - info.m_itemId = item; + return (tvItem.state & TVIS_BOLD) != 0; +*/ + return FALSE; +} - return SetItem(info); +// ---------------------------------------------------------------------------- +// navigation +// ---------------------------------------------------------------------------- + +wxTreeItemId wxTreeCtrl::GetRootItem() const +{ +// return wxTreeItemId((WXHTREEITEM) TreeView_GetRoot(GetHwnd())); + return 0; } -bool wxTreeCtrl::SetItemImage(long item, int image, int selImage) +wxTreeItemId wxTreeCtrl::GetSelection() const { - wxTreeItem info; + wxCHECK_MSG( !(m_windowStyle & wxTR_MULTIPLE), (WXHTREEITEM)0, + wxT("this only works with single selection controls") ); - info.m_mask = wxTREE_MASK_IMAGE ; - info.m_image = image; - if ( selImage > -1) - { - info.m_selectedImage = selImage; - info.m_mask |= wxTREE_MASK_SELECTED_IMAGE; - } - info.m_itemId = item; +// return wxTreeItemId((WXHTREEITEM) TreeView_GetSelection(GetHwnd())); + return 0; +} - return SetItem(info); +wxTreeItemId wxTreeCtrl::GetParent(const wxTreeItemId& item) const +{ +// return wxTreeItemId((WXHTREEITEM) TreeView_GetParent(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); + return 0; } -wxString wxTreeCtrl::GetItemText(long item) const +wxTreeItemId wxTreeCtrl::GetFirstChild(const wxTreeItemId& item, + long& _cookie) const { - wxTreeItem info; +// TODO: +/* + // remember the last child returned in 'cookie' + _cookie = (long)TreeView_GetChild(GetHwnd(), (HTREEITEM) (WXHTREEITEM)item); + + return wxTreeItemId((WXHTREEITEM)_cookie); +*/ + return 0; +} - info.m_mask = wxTREE_MASK_TEXT ; - info.m_itemId = item; +wxTreeItemId wxTreeCtrl::GetNextChild(const wxTreeItemId& WXUNUSED(item), + long& _cookie) const +{ + wxTreeItemId l = 0; //wxTreeItemId((WXHTREEITEM)TreeView_GetNextSibling(GetHwnd(), +// (HTREEITEM)(WXHTREEITEM)_cookie)); + _cookie = (long)l; - if (!GetItem(info)) - return wxString(""); - return info.m_text; + return l; } -void wxTreeCtrl::SetItemText(long item, const wxString& str) +wxTreeItemId wxTreeCtrl::GetLastChild(const wxTreeItemId& item) const { - wxTreeItem info; + // can this be done more efficiently? + long cookie; - info.m_mask = wxTREE_MASK_TEXT ; - info.m_itemId = item; - info.m_text = str; + wxTreeItemId childLast, + child = GetFirstChild(item, cookie); + while ( child.IsOk() ) + { + childLast = child; + child = GetNextChild(item, cookie); + } - SetItem(info); + return childLast; } -long wxTreeCtrl::GetItemData(long item) const +wxTreeItemId wxTreeCtrl::GetNextSibling(const wxTreeItemId& item) const { - wxTreeItem info; +// return wxTreeItemId((WXHTREEITEM) TreeView_GetNextSibling(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); + return 0; +} - info.m_mask = wxTREE_MASK_DATA ; - info.m_itemId = item; +wxTreeItemId wxTreeCtrl::GetPrevSibling(const wxTreeItemId& item) const +{ +// return wxTreeItemId((WXHTREEITEM) TreeView_GetPrevSibling(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); + return 0; +} - if (!GetItem(info)) - return 0; - return info.m_data; +wxTreeItemId wxTreeCtrl::GetFirstVisibleItem() const +{ +// return wxTreeItemId((WXHTREEITEM) TreeView_GetFirstVisible(GetHwnd())); + return 0; } -bool wxTreeCtrl::SetItemData(long item, long data) +wxTreeItemId wxTreeCtrl::GetNextVisible(const wxTreeItemId& item) const { - wxTreeItem info; + wxASSERT_MSG( IsVisible(item), wxT("The item you call GetNextVisible() " + "for must be visible itself!")); + +// return wxTreeItemId((WXHTREEITEM) TreeView_GetNextVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); + return 0; +} - info.m_mask = wxTREE_MASK_DATA ; - info.m_itemId = item; - info.m_data = data; +wxTreeItemId wxTreeCtrl::GetPrevVisible(const wxTreeItemId& item) const +{ + wxASSERT_MSG( IsVisible(item), wxT("The item you call GetPrevVisible() " + "for must be visible itself!")); - return SetItem(info); +// return wxTreeItemId((WXHTREEITEM) TreeView_GetPrevVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item)); + return 0; } -bool wxTreeCtrl::GetItemRect(long item, wxRect& rect, bool textOnly) const +// ---------------------------------------------------------------------------- +// multiple selections emulation +// ---------------------------------------------------------------------------- + +bool wxTreeCtrl::IsItemChecked(const wxTreeItemId& item) const { - // TODO + // receive the desired information. +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK); + DoGetItem(&tvItem); + + // state image indices are 1 based + return ((tvItem.state >> 12) - 1) == 1; +*/ return FALSE; } -wxTextCtrl* wxTreeCtrl::GetEditControl() const +void wxTreeCtrl::SetItemCheck(const wxTreeItemId& item, bool check) { - return m_textCtrl; + // receive the desired information. +// TODO: +/* + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK); + + // state images are one-based + tvItem.state = (check ? 2 : 1) << 12; + + DoSetItem(&tvItem); +*/ } -// Operations -bool wxTreeCtrl::DeleteItem(long item) +size_t wxTreeCtrl::GetSelections(wxArrayTreeItemIds& selections) const { - // TODO - return FALSE; + TraverseSelections selector(this, selections); + + return selections.GetCount(); } -bool wxTreeCtrl::ExpandItem(long item, int action) +// ---------------------------------------------------------------------------- +// Usual operations +// ---------------------------------------------------------------------------- + +wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parent, + wxTreeItemId hInsertAfter, + const wxString& text, + int image, int selectedImage, + wxTreeItemData *data) { - // TODO - switch ( action ) - { - case wxTREE_EXPAND_EXPAND: - break; +// TODO: +/* + TV_INSERTSTRUCT tvIns; + tvIns.hParent = (HTREEITEM) (WXHTREEITEM)parent; + tvIns.hInsertAfter = (HTREEITEM) (WXHTREEITEM) hInsertAfter; + + // this is how we insert the item as the first child: supply a NULL + // hInsertAfter + if ( !tvIns.hInsertAfter ) + { + tvIns.hInsertAfter = TVI_FIRST; + } - case wxTREE_EXPAND_COLLAPSE: - break; + UINT mask = 0; + if ( !text.IsEmpty() ) + { + mask |= TVIF_TEXT; + tvIns.item.pszText = (wxChar *)text.c_str(); // cast is ok + } - case wxTREE_EXPAND_COLLAPSE_RESET: - break; + if ( image != -1 ) + { + mask |= TVIF_IMAGE; + tvIns.item.iImage = image; + + if ( selectedImage == -1 ) + { + // take the same image for selected icon if not specified + selectedImage = image; + } + } - case wxTREE_EXPAND_TOGGLE: - break; + if ( selectedImage != -1 ) + { + mask |= TVIF_SELECTEDIMAGE; + tvIns.item.iSelectedImage = selectedImage; + } - default: - wxFAIL_MSG("unknown action in wxTreeCtrl::ExpandItem"); - } + if ( data != NULL ) + { + mask |= TVIF_PARAM; + tvIns.item.lParam = (LPARAM)data; + } - bool bOk = FALSE; // TODO expand item + tvIns.item.mask = mask; - // May not send messages, so emulate them - if ( bOk ) { - wxTreeEvent event(wxEVT_NULL, m_windowId); - event.m_item.m_itemId = item; - event.m_item.m_mask = - event.m_item.m_stateMask = 0xffff; // get all - GetItem(event.m_item); + HTREEITEM id = (HTREEITEM) TreeView_InsertItem(GetHwnd(), &tvIns); + if ( id == 0 ) + { + wxLogLastError("TreeView_InsertItem"); + } + + if ( data != NULL ) + { + // associate the application tree item with Win32 tree item handle + data->SetId((WXHTREEITEM)id); + } - bool bIsExpanded = (event.m_item.m_state & wxTREE_STATE_EXPANDED) != 0; + return wxTreeItemId((WXHTREEITEM)id); +*/ + return 0; +} - event.m_code = action; - event.SetEventObject(this); +// for compatibility only +wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent, + const wxString& text, + int image, int selImage, + long insertAfter) +{ + return DoInsertItem(parent, (WXHTREEITEM)insertAfter, text, + image, selImage, NULL); +} - // @@@ return values of {EXPAND|COLLAPS}ING event handler is discarded - event.SetEventType(bIsExpanded ? wxEVT_COMMAND_TREE_ITEM_EXPANDING - : wxEVT_COMMAND_TREE_ITEM_COLLAPSING); - GetEventHandler()->ProcessEvent(event); +wxTreeItemId wxTreeCtrl::AddRoot(const wxString& text, + int image, int selectedImage, + wxTreeItemData *data) +{ + return DoInsertItem(wxTreeItemId((WXHTREEITEM) 0), (WXHTREEITEM) 0, + text, image, selectedImage, data); +} - event.SetEventType(bIsExpanded ? wxEVT_COMMAND_TREE_ITEM_EXPANDED - : wxEVT_COMMAND_TREE_ITEM_COLLAPSED); - GetEventHandler()->ProcessEvent(event); - } +wxTreeItemId wxTreeCtrl::PrependItem(const wxTreeItemId& parent, + const wxString& text, + int image, int selectedImage, + wxTreeItemData *data) +{ +// TODO: +/* + return DoInsertItem(parent, (WXHTREEITEM) TVI_FIRST, + text, image, selectedImage, data); +*/ + return 0; +} - return bOk; +wxTreeItemId wxTreeCtrl::InsertItem(const wxTreeItemId& parent, + const wxTreeItemId& idPrevious, + const wxString& text, + int image, int selectedImage, + wxTreeItemData *data) +{ + return DoInsertItem(parent, idPrevious, text, image, selectedImage, data); } -long wxTreeCtrl::InsertItem(long parent, wxTreeItem& info, long insertAfter) +wxTreeItemId wxTreeCtrl::AppendItem(const wxTreeItemId& parent, + const wxString& text, + int image, int selectedImage, + wxTreeItemData *data) { - // TODO +// TODO: +/* + return DoInsertItem(parent, (WXHTREEITEM) TVI_LAST, + text, image, selectedImage, data); +*/ return 0; } -long wxTreeCtrl::InsertItem(long parent, const wxString& label, int image, int selImage, - long insertAfter) +void wxTreeCtrl::Delete(const wxTreeItemId& item) { - wxTreeItem info; - info.m_text = label; - info.m_mask = wxTREE_MASK_TEXT; - if ( image > -1 ) +// TODO: +/* + if ( !TreeView_DeleteItem(GetHwnd(), (HTREEITEM)(WXHTREEITEM)item) ) { - info.m_mask |= wxTREE_MASK_IMAGE | wxTREE_MASK_SELECTED_IMAGE; - info.m_image = image; - if ( selImage == -1 ) - info.m_selectedImage = image; - else - info.m_selectedImage = selImage; + wxLogLastError("TreeView_DeleteItem"); + } +*/ +} + +// delete all children (but don't delete the item itself) +void wxTreeCtrl::DeleteChildren(const wxTreeItemId& item) +{ + long cookie; + + wxArrayLong children; + wxTreeItemId child = GetFirstChild(item, cookie); + while ( child.IsOk() ) + { + children.Add((long)(WXHTREEITEM)child); + + child = GetNextChild(item, cookie); } - return InsertItem(parent, info, insertAfter); + size_t nCount = children.Count(); +// TODO: +/* + for ( size_t n = 0; n < nCount; n++ ) + { + if ( !TreeView_DeleteItem(GetHwnd(), (HTREEITEM)children[n]) ) + { + wxLogLastError("TreeView_DeleteItem"); + } + } +*/ } -bool wxTreeCtrl::SelectItem(long item) +void wxTreeCtrl::DeleteAllItems() { - // TODO - return FALSE; +// TODO: +/* + if ( !TreeView_DeleteAllItems(GetHwnd()) ) + { + wxLogLastError("TreeView_DeleteAllItems"); + } +*/ } -bool wxTreeCtrl::ScrollTo(long item) +void wxTreeCtrl::DoExpand(const wxTreeItemId& item, int flag) { - // TODO - return FALSE; +// TODO: +/* + wxASSERT_MSG( flag == TVE_COLLAPSE || + flag == (TVE_COLLAPSE | TVE_COLLAPSERESET) || + flag == TVE_EXPAND || + flag == TVE_TOGGLE, + wxT("Unknown flag in wxTreeCtrl::DoExpand") ); + + // TreeView_Expand doesn't send TVN_ITEMEXPAND(ING) messages, so we must + // emulate them. This behaviour has changed slightly with comctl32.dll + // v 4.70 - now it does send them but only the first time. To maintain + // compatible behaviour and also in order to not have surprises with the + // future versions, don't rely on this and still do everything ourselves. + // To avoid that the messages be sent twice when the item is expanded for + // the first time we must clear TVIS_EXPANDEDONCE style manually. + + wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_EXPANDEDONCE); + tvItem.state = 0; + DoSetItem(&tvItem); + + if ( TreeView_Expand(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item, flag) != 0 ) + { + wxTreeEvent event(wxEVT_NULL, m_windowId); + event.m_item = item; + + bool isExpanded = IsExpanded(item); + + event.SetEventObject(this); + + // FIXME return value of {EXPAND|COLLAPS}ING event handler is discarded + event.SetEventType(g_events[isExpanded][TRUE]); + GetEventHandler()->ProcessEvent(event); + + event.SetEventType(g_events[isExpanded][FALSE]); + GetEventHandler()->ProcessEvent(event); + } + //else: change didn't took place, so do nothing at all +*/ } -bool wxTreeCtrl::DeleteAllItems() +void wxTreeCtrl::Expand(const wxTreeItemId& item) { - // TODO - return FALSE; +// DoExpand(item, TVE_EXPAND); } -wxTextCtrl* wxTreeCtrl::EditLabel(long item, wxClassInfo* textControlClass) +void wxTreeCtrl::Collapse(const wxTreeItemId& item) { - // TODO - return NULL; +// DoExpand(item, TVE_COLLAPSE); +} + +void wxTreeCtrl::CollapseAndReset(const wxTreeItemId& item) +{ +// DoExpand(item, TVE_COLLAPSE | TVE_COLLAPSERESET); +} + +void wxTreeCtrl::Toggle(const wxTreeItemId& item) +{ +// DoExpand(item, TVE_TOGGLE); +} + +void wxTreeCtrl::ExpandItem(const wxTreeItemId& item, int action) +{ +// DoExpand(item, action); +} + +void wxTreeCtrl::Unselect() +{ + wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE), wxT("doesn't make sense") ); + + // just remove the selection +// SelectItem(wxTreeItemId((WXHTREEITEM) 0)); +} + +void wxTreeCtrl::UnselectAll() +{ + if ( m_windowStyle & wxTR_MULTIPLE ) + { + wxArrayTreeItemIds selections; + size_t count = GetSelections(selections); + for ( size_t n = 0; n < count; n++ ) + { + SetItemCheck(selections[n], FALSE); + } + } + else + { + // just remove the selection + Unselect(); + } +} + +void wxTreeCtrl::SelectItem(const wxTreeItemId& item) +{ + if ( m_windowStyle & wxTR_MULTIPLE ) + { + // selecting the item means checking it + SetItemCheck(item); + } + else + { + // inspite of the docs (MSDN Jan 99 edition), we don't seem to receive + // the notification from the control (i.e. TVN_SELCHANG{ED|ING}), so + // send them ourselves + + wxTreeEvent event(wxEVT_NULL, m_windowId); + event.m_item = item; + event.SetEventObject(this); + + event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGING); +// TODO: +/* + if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() ) + { + if ( !TreeView_SelectItem(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item) ) + { + wxLogLastError("TreeView_SelectItem"); + } + else + { + event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); + (void)GetEventHandler()->ProcessEvent(event); + } + } + //else: program vetoed the change +*/ + } +} + +void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item) +{ + // no error return +// TreeView_EnsureVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item); +} + +void wxTreeCtrl::ScrollTo(const wxTreeItemId& item) +{ +// TODO: +/* + if ( !TreeView_SelectSetFirstVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item) ) + { + wxLogLastError("TreeView_SelectSetFirstVisible"); + } +*/ +} + +wxTextCtrl* wxTreeCtrl::GetEditControl() const +{ + return m_textCtrl; +} + +void wxTreeCtrl::DeleteTextCtrl() +{ + if ( m_textCtrl ) + { + m_textCtrl->UnsubclassWin(); + m_textCtrl->SetHWND(0); + delete m_textCtrl; + m_textCtrl = NULL; + } +} + +wxTextCtrl* wxTreeCtrl::EditLabel(const wxTreeItemId& item, + wxClassInfo* textControlClass) +{ + wxASSERT( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)) ); + +// TODO: +/* + HWND hWnd = (HWND) TreeView_EditLabel(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item); + + // this is not an error - the TVN_BEGINLABELEDIT handler might have + // returned FALSE + if ( !hWnd ) + { + return NULL; + } + + DeleteTextCtrl(); + + m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject(); + m_textCtrl->SetHWND((WXHWND)hWnd); + m_textCtrl->SubclassWin((WXHWND)hWnd); +*/ + return m_textCtrl; } // End label editing, optionally cancelling the edit -bool wxTreeCtrl::EndEditLabel(bool cancel) +void wxTreeCtrl::EndEditLabel(const wxTreeItemId& item, bool discardChanges) { - // TODO - return FALSE; +// TreeView_EndEditLabelNow(GetHwnd(), discardChanges); + + DeleteTextCtrl(); } -long wxTreeCtrl::HitTest(const wxPoint& point, int& flags) +wxTreeItemId wxTreeCtrl::HitTest(const wxPoint& point, int& flags) { - // TODO +// TODO: +/* + TV_HITTESTINFO hitTestInfo; + hitTestInfo.pt.x = (int)point.x; + hitTestInfo.pt.y = (int)point.y; + + TreeView_HitTest(GetHwnd(), &hitTestInfo); + + flags = 0; + + // avoid repetition + #define TRANSLATE_FLAG(flag) if ( hitTestInfo.flags & TVHT_##flag ) \ + flags |= wxTREE_HITTEST_##flag + + TRANSLATE_FLAG(ABOVE); + TRANSLATE_FLAG(BELOW); + TRANSLATE_FLAG(NOWHERE); + TRANSLATE_FLAG(ONITEMBUTTON); + TRANSLATE_FLAG(ONITEMICON); + TRANSLATE_FLAG(ONITEMINDENT); + TRANSLATE_FLAG(ONITEMLABEL); + TRANSLATE_FLAG(ONITEMRIGHT); + TRANSLATE_FLAG(ONITEMSTATEICON); + TRANSLATE_FLAG(TOLEFT); + TRANSLATE_FLAG(TORIGHT); + + #undef TRANSLATE_FLAG + + return wxTreeItemId((WXHTREEITEM) hitTestInfo.hItem); +*/ return 0; } -bool wxTreeCtrl::SortChildren(long item) +bool wxTreeCtrl::GetBoundingRect(const wxTreeItemId& item, + wxRect& rect, + bool textOnly) const { - // TODO +// TODO: +/* + RECT rc; + if ( TreeView_GetItemRect(GetHwnd(), (HTREEITEM)(WXHTREEITEM)item, + &rc, textOnly) ) + { + rect = wxRect(wxPoint(rc.left, rc.top), wxPoint(rc.right, rc.bottom)); + + return TRUE; + } + else + { + // couldn't retrieve rect: for example, item isn't visible + return FALSE; + } +*/ return FALSE; } -bool wxTreeCtrl::EnsureVisible(long item) +// ---------------------------------------------------------------------------- +// sorting stuff +// ---------------------------------------------------------------------------- + +static int TreeView_CompareCallback(wxTreeItemData *pItem1, + wxTreeItemData *pItem2, + wxTreeCtrl *tree) +{ + wxCHECK_MSG( pItem1 && pItem2, 0, + wxT("sorting tree without data doesn't make sense") ); + + return tree->OnCompareItems(pItem1->GetId(), pItem2->GetId()); +} + +int wxTreeCtrl::OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2) +{ + return wxStrcmp(GetItemText(item1), GetItemText(item2)); +} + +void wxTreeCtrl::SortChildren(const wxTreeItemId& item) +{ + // rely on the fact that TreeView_SortChildren does the same thing as our + // default behaviour, i.e. sorts items alphabetically and so call it + // directly if we're not in derived class (much more efficient!) +// TODO: +/* + if ( GetClassInfo() == CLASSINFO(wxTreeCtrl) ) + { + TreeView_SortChildren(GetHwnd(), (HTREEITEM)(WXHTREEITEM)item, 0); + } + else + { + TV_SORTCB tvSort; + tvSort.hParent = (HTREEITEM)(WXHTREEITEM)item; + tvSort.lpfnCompare = (PFNTVCOMPARE)TreeView_CompareCallback; + tvSort.lParam = (LPARAM)this; + TreeView_SortChildrenCB(GetHwnd(), &tvSort, 0); + } +*/ +} + +// ---------------------------------------------------------------------------- +// implementation +// ---------------------------------------------------------------------------- + +bool wxTreeCtrl::OS2Command(WXUINT cmd, WXWORD id) { - // TODO +// TODO: +/* + if ( cmd == EN_UPDATE ) + { + wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id); + event.SetEventObject( this ); + ProcessCommand(event); + } + else if ( cmd == EN_KILLFOCUS ) + { + wxCommandEvent event(wxEVT_KILL_FOCUS, id); + event.SetEventObject( this ); + ProcessCommand(event); + } + else + { + // nothing done + return FALSE; + } + + // command processed + return TRUE; +*/ return FALSE; } -// Tree item structure -wxTreeItem::wxTreeItem() +// process WM_NOTIFY Windows message +bool wxTreeCtrl::OS2OnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) { - m_mask = 0; - m_itemId = 0; - m_state = 0; - m_stateMask = 0; - m_image = -1; - m_selectedImage = -1; - m_children = 0; - m_data = 0; +// TODO: +/* + wxTreeEvent event(wxEVT_NULL, m_windowId); + wxEventType eventType = wxEVT_NULL; + NMHDR *hdr = (NMHDR *)lParam; + + switch ( hdr->code ) + { + case NM_RCLICK: + { + if ( wxControl::MSWOnNotify(idCtrl, lParam, result) ) + return TRUE; + + TV_HITTESTINFO tvhti; + ::GetCursorPos(&(tvhti.pt)); + ::ScreenToClient(GetHwnd(),&(tvhti.pt)); + if ( TreeView_HitTest(GetHwnd(),&tvhti) ) + { + if( tvhti.flags & TVHT_ONITEM ) + { + event.m_item = (WXHTREEITEM) tvhti.hItem; + eventType=wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK; + } + } + break; + } + + case TVN_BEGINDRAG: + eventType = wxEVT_COMMAND_TREE_BEGIN_DRAG; + // fall through + + case TVN_BEGINRDRAG: + { + if ( eventType == wxEVT_NULL ) + eventType = wxEVT_COMMAND_TREE_BEGIN_RDRAG; + //else: left drag, already set above + + NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam; + + event.m_item = (WXHTREEITEM) tv->itemNew.hItem; + event.m_pointDrag = wxPoint(tv->ptDrag.x, tv->ptDrag.y); + break; + } + + case TVN_BEGINLABELEDIT: + { + eventType = wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT; + TV_DISPINFO *info = (TV_DISPINFO *)lParam; + + event.m_item = (WXHTREEITEM) info->item.hItem; + event.m_label = info->item.pszText; + break; + } + + case TVN_DELETEITEM: + { + eventType = wxEVT_COMMAND_TREE_DELETE_ITEM; + NM_TREEVIEW *tv = (NM_TREEVIEW *)lParam; + + event.m_item = (WXHTREEITEM) tv->itemOld.hItem; + break; + } + + case TVN_ENDLABELEDIT: + { + eventType = wxEVT_COMMAND_TREE_END_LABEL_EDIT; + TV_DISPINFO *info = (TV_DISPINFO *)lParam; + + event.m_item = (WXHTREEITEM)info->item.hItem; + event.m_label = info->item.pszText; + break; + } + + case TVN_GETDISPINFO: + eventType = wxEVT_COMMAND_TREE_GET_INFO; + // fall through + + case TVN_SETDISPINFO: + { + if ( eventType == wxEVT_NULL ) + eventType = wxEVT_COMMAND_TREE_SET_INFO; + //else: get, already set above + + TV_DISPINFO *info = (TV_DISPINFO *)lParam; + + event.m_item = (WXHTREEITEM) info->item.hItem; + break; + } + + case TVN_ITEMEXPANDING: + event.m_code = FALSE; + // fall through + + case TVN_ITEMEXPANDED: + { + NM_TREEVIEW* tv = (NM_TREEVIEW*)lParam; + + bool expand = FALSE; + switch ( tv->action ) + { + case TVE_EXPAND: + expand = TRUE; + break; + + case TVE_COLLAPSE: + expand = FALSE; + break; + + default: + wxLogDebug(wxT("unexpected code %d in TVN_ITEMEXPAND " + "message"), tv->action); + } + + bool ing = ((int)hdr->code == TVN_ITEMEXPANDING); + eventType = g_events[expand][ing]; + + event.m_item = (WXHTREEITEM) tv->itemNew.hItem; + break; + } + + case TVN_KEYDOWN: + { + eventType = wxEVT_COMMAND_TREE_KEY_DOWN; + TV_KEYDOWN *info = (TV_KEYDOWN *)lParam; + + event.m_code = wxCharCodeMSWToWX(info->wVKey); + + // a separate event for this case + if ( info->wVKey == VK_SPACE || info->wVKey == VK_RETURN ) + { + wxTreeEvent event2(wxEVT_COMMAND_TREE_ITEM_ACTIVATED, + m_windowId); + event2.SetEventObject(this); + + GetEventHandler()->ProcessEvent(event2); + } + break; + } + + case TVN_SELCHANGED: + eventType = wxEVT_COMMAND_TREE_SEL_CHANGED; + // fall through + + case TVN_SELCHANGING: + { + if ( eventType == wxEVT_NULL ) + eventType = wxEVT_COMMAND_TREE_SEL_CHANGING; + //else: already set above + + NM_TREEVIEW* tv = (NM_TREEVIEW *)lParam; + + event.m_item = (WXHTREEITEM) tv->itemNew.hItem; + event.m_itemOld = (WXHTREEITEM) tv->itemOld.hItem; + break; + } + + default: + return wxControl::MSWOnNotify(idCtrl, lParam, result); + } + + event.SetEventObject(this); + event.SetEventType(eventType); + + bool processed = GetEventHandler()->ProcessEvent(event); + + // post processing + switch ( hdr->code ) + { + case TVN_DELETEITEM: + { + // NB: we might process this message using wxWindows event + // tables, but due to overhead of wxWin event system we + // prefer to do it here ourself (otherwise deleting a tree + // with many items is just too slow) + NM_TREEVIEW* tv = (NM_TREEVIEW *)lParam; + + wxTreeItemId item = event.m_item; + if ( HasIndirectData(item) ) + { + wxTreeItemIndirectData *data = (wxTreeItemIndirectData *) + tv->itemOld.lParam; + delete data; // can't be NULL here + + m_itemsWithIndirectData.Remove(item); + } + else + { + wxTreeItemData *data = (wxTreeItemData *)tv->itemOld.lParam; + delete data; // may be NULL, ok + } + + processed = TRUE; // Make sure we don't get called twice + } + break; + + case TVN_BEGINLABELEDIT: + // return TRUE to cancel label editing + *result = !event.IsAllowed(); + break; + + case TVN_ENDLABELEDIT: + // return TRUE to set the label to the new string + *result = event.IsAllowed(); + + // ensure that we don't have the text ctrl which is going to be + // deleted any more + DeleteTextCtrl(); + break; + + case TVN_SELCHANGING: + case TVN_ITEMEXPANDING: + // return TRUE to prevent the action from happening + *result = !event.IsAllowed(); + break; + + case TVN_GETDISPINFO: + // NB: so far the user can't set the image himself anyhow, so do it + // anyway - but this may change later + if ( 1 // !processed && ) + { + wxTreeItemId item = event.m_item; + TV_DISPINFO *info = (TV_DISPINFO *)lParam; + if ( info->item.mask & TVIF_IMAGE ) + { + info->item.iImage = + DoGetItemImageFromData + ( + item, + IsExpanded(item) ? wxTreeItemIcon_Expanded + : wxTreeItemIcon_Normal + ); + } + if ( info->item.mask & TVIF_SELECTEDIMAGE ) + { + info->item.iSelectedImage = + DoGetItemImageFromData + ( + item, + IsExpanded(item) ? wxTreeItemIcon_SelectedExpanded + : wxTreeItemIcon_Selected + ); + } + } + break; + + //default: + // for the other messages the return value is ignored and there is + // nothing special to do + } + + return processed; +*/ + return FALSE; } +// ---------------------------------------------------------------------------- // Tree event -IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxCommandEvent) +// ---------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxNotifyEvent) -wxTreeEvent::wxTreeEvent(wxEventType commandType, int id): - wxCommandEvent(commandType, id) +wxTreeEvent::wxTreeEvent(wxEventType commandType, int id) + : wxNotifyEvent(commandType, id) { m_code = 0; - m_oldItem = 0; + m_itemOld = 0; } diff --git a/src/os2/utils.cpp b/src/os2/utils.cpp index 10100cb58a..d494fca7a4 100644 --- a/src/os2/utils.cpp +++ b/src/os2/utils.cpp @@ -9,10 +9,6 @@ // Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -// #pragma implementation "utils.h" // Note: this is done in utilscmn.cpp now. -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -40,10 +36,12 @@ #include #include -#define INCL_OS2 +#define INCL_DOS #define INCL_PM +#define INCL_GPI #include #include +#define PURE_32 #include // In the WIN.INI file @@ -60,7 +58,7 @@ static const wxChar eUSERNAME[] = _T("UserName"); // Get full hostname (eg. DoDo.BSn-Germany.crg.de) bool wxGetHostName(wxChar *buf, int maxSize) { -#ifdef USE_NET_API +#if wxUSE_NET_API char server[256]; char computer[256]; unsigned long ulLevel; @@ -80,10 +78,12 @@ bool wxGetHostName(wxChar *buf, int maxSize) wxChar *sysname; const wxChar *default_host = _T("noname"); - if ((sysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL) { - GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1); - } else - wxStrncpy(buf, sysname, maxSize - 1); + if ((sysname = wxGetenv(_T("SYSTEM_NAME"))) == NULL) + { + // GetProfileString(WX_SECTION, eHOSTNAME, default_host, buf, maxSize - 1); + } + else + wxStrncpy(buf, sysname, maxSize - 1); buf[maxSize] = _T('\0'); #endif return *buf ? TRUE : FALSE; @@ -92,7 +92,7 @@ bool wxGetHostName(wxChar *buf, int maxSize) // Get user ID e.g. jacs bool wxGetUserId(wxChar *buf, int maxSize) { - return(U32ELOCL(bub, maxSize)); + return(U32ELOCL((unsigned char*)buf, (unsigned long *)&maxSize)); } bool wxGetUserName(wxChar *buf, int maxSize) @@ -100,16 +100,7 @@ bool wxGetUserName(wxChar *buf, int maxSize) #ifdef USE_NET_API wxGetUserId(buf, maxSize); #else - bool ok = GetProfileString(WX_SECTION, eUSERNAME, _T(""), buf, maxSize - 1) != 0; - if ( !ok ) - { - ok = wxGetUserId(buf, maxSize); - } - - if ( !ok ) - { - wxStrncpy(buf, _T("Unknown User"), maxSize); - } + wxStrncpy(buf, _T("Unknown User"), maxSize); #endif return TRUE; } @@ -140,7 +131,8 @@ bool wxShell(const wxString& command) // Get free memory in bytes, or -1 if cannot determine amount (e.g. on UNIX) long wxGetFreeMemory() { - return (long)GetFreeSpace(0); + // return (long)GetFreeSpace(0); + return 0L; } // Sleep for nSecs seconds. Attempt a Windows implementation using timers. @@ -198,7 +190,6 @@ void wxDebugMsg(const wxChar *fmt ...) va_start(ap, fmt); sprintf(buffer,fmt,ap) ; - fflush(buffer) ; va_end(ap); } @@ -211,24 +202,24 @@ void wxError(const wxString& msg, const wxString& title) ,NULL ,(PSZ)wxBuffer ,(PSZ)WXSTRINGCAST title + ,0 ,MB_ICONEXCLAMATION | MB_YESNO - ) == IDNO) + ) == MBID_YES) wxExit(); } // Fatal error: pop up message box and abort -void wxFatalError(const wxString& msg, const wxString& title) -{ - YUint32 rc; - HWND hWnd; - - WinMessageBox( HWND_DESKTOP - ,hWnd - ,rMsg.Data() - ,rTitle.Data() - ,0 - ,MB_NOICON | MB_OK - ); +void wxFatalError(const wxString& rMsg, const wxString& rTitle) +{ + unsigned long rc; + + rc = ::WinMessageBox( HWND_DESKTOP + ,NULL + ,WXSTRINGCAST rMsg + ,WXSTRINGCAST rTitle + ,0 + ,MB_NOICON | MB_OK + ); DosExit(EXIT_PROCESS, rc); } @@ -258,13 +249,19 @@ int wxGetOsVersion(int *majorVsn, int *minorVsn) } // Reading and writing resources (eg WIN.INI, .Xdefaults) +// TODO: Ability to read and write to an INI file + #if wxUSE_RESOURCES bool wxWriteResource(const wxString& section, const wxString& entry, const wxString& value, const wxString& file) { +// TODO: +/* if (file != "") return (WritePrivateProfileString((PCSZ)WXSTRINGCAST section, (PCSZ)WXSTRINGCAST entry, (PCSZ)value, (PCSZ)WXSTRINGCAST file) != 0); else return (WriteProfileString((PCSZ)WXSTRINGCAST section, (PCSZ)WXSTRINGCAST entry, (PCSZ)WXSTRINGCAST value) != 0); +*/ + return FALSE; } bool wxWriteResource(const wxString& section, const wxString& entry, float value, const wxString& file) @@ -291,6 +288,8 @@ bool wxWriteResource(const wxString& section, const wxString& entry, int value, bool wxGetResource(const wxString& section, const wxString& entry, wxChar **value, const wxString& file) { static const wxChar defunkt[] = _T("$$default"); +// TODO: +/* if (file != "") { int n = GetPrivateProfileString((PCSZ)WXSTRINGCAST section, (PCSZ)WXSTRINGCAST entry, (PCSZ)defunkt, @@ -308,7 +307,9 @@ bool wxGetResource(const wxString& section, const wxString& entry, wxChar **valu if (*value) delete[] (*value); *value = copystring(wxBuffer); return TRUE; - } +*/ + return FALSE; +} bool wxGetResource(const wxString& section, const wxString& entry, float *value, const wxString& file) { @@ -452,7 +453,7 @@ bool wxCheckForInterrupt(wxWindow *wnd) HWND win= (HWND) wnd->GetHWND(); while(::WinPeekMsg(hab,&msg,hwndFilter,0,0,PM_REMOVE)) { - ::WinDispatchMsg( hab, &qmsg ); + ::WinDispatchMsg( hab, &msg ); } return TRUE;//*** temporary? } @@ -488,16 +489,16 @@ wxChar *wxLoadUserResource(const wxString& resourceName, const wxString& resourc * wxChar *theText = (wxChar *)LockResource(hData); * if (!theText) * return NULL; +* +* s = copystring(theText); */ - s = copystring(theText); - return s; } void wxGetMousePosition( int* x, int* y ) { - POINT pt; - GetCursorPos( & pt ); + POINTL pt; + ::WinQueryPointerPos( HWND_DESKTOP, & pt ); *x = pt.x; *y = pt.y; }; @@ -530,7 +531,7 @@ int wxDisplayDepth() nDepth = nPlanes * nBitsPerPixel; } DevCloseDC(hDc); - return (depth); + return (nDepth); } // Get size of display @@ -545,8 +546,8 @@ void wxDisplaySize(int *width, int *height) ,lArray )) { - *pWidth = (int)lArray[CAPS_WIDTH]; - *pHeight = (int)lArray[CAPS_HEIGHT]; + *width = (int)lArray[CAPS_WIDTH]; + *height = (int)lArray[CAPS_HEIGHT]; } DevCloseDC(hDc); } @@ -565,7 +566,7 @@ wxString WXDLLEXPORT wxGetWindowText(WXHWND hWnd) { wxString str; long len = ::WinQueryWindowTextLength((HWND)hWnd) + 1; - ::WinQueryWindowText((HWND)hWnd, str.GetWriteBuf((int)len), len); + ::WinQueryWindowText((HWND)hWnd, len, str.GetWriteBuf((int)len)); str.UngetWriteBuf(); return str; @@ -579,7 +580,7 @@ wxString WXDLLEXPORT wxGetWindowClass(WXHWND hWnd) for ( ;; ) { - int count = ::WinQueryClassName((HWND)hWnd, str.GetWriteBuf(len), len); + int count = ::WinQueryClassName((HWND)hWnd, len, str.GetWriteBuf(len)); str.UngetWriteBuf(); if ( count == len ) diff --git a/src/os2/utilsexc.cpp b/src/os2/utilsexc.cpp index b842d08e90..4c6c00399e 100644 --- a/src/os2/utilsexc.cpp +++ b/src/os2/utilsexc.cpp @@ -1,28 +1,262 @@ ///////////////////////////////////////////////////////////////////////////// // Name: utilsexec.cpp -// Purpose: Execution-related utilities -// Author: AUTHOR +// Purpose: Various utilities +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" +#ifndef WX_PRECOMP +#include "wx/setup.h" #include "wx/utils.h" +#include "wx/app.h" +#include "wx/intl.h" +#endif + +#include "wx/log.h" + +#include "wx/process.h" + +#include "wx/os2/private.h" + +#define INCL_DOS +#include + +#include +#include + +#include +#include #include #include #include +#include +#include + +// this message is sent when the process we're waiting for terminates +#define wxWM_PROC_TERMINATED (WM_USER + 10000) + +// structure describing the process we're being waiting for +struct wxExecuteData +{ +public: + ~wxExecuteData() + { +// TODO: +/* + if ( !::CloseHandle(hProcess) ) + { + wxLogLastError("CloseHandle(hProcess)"); + } +*/ + } + + HWND hWnd; // window to send wxWM_PROC_TERMINATED to + HANDLE hProcess; // handle of the process + DWORD dwProcessId; // pid of the process + wxProcess *handler; + DWORD dwExitCode; // the exit code of the process + bool state; // set to FALSE when the process finishes +}; + + +static DWORD wxExecuteThread(wxExecuteData *data) +{ +// TODO: +/* + WaitForSingleObject(data->hProcess, INFINITE); -#define wxEXECUTE_WIN_MESSAGE 10000 + // get the exit code + if ( !GetExitCodeProcess(data->hProcess, &data->dwExitCode) ) + { + wxLogLastError("GetExitCodeProcess"); + } + + wxASSERT_MSG( data->dwExitCode != STILL_ACTIVE, + wxT("process should have terminated") ); + + // send a message indicating process termination to the window + SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data); +*/ + return 0; +} + +// window procedure of a hidden window which is created just to receive +// the notification message when a process exits +MRESULT APIENTRY wxExecuteWindowCbk(HWND hWnd, UINT message, + MPARAM wParam, MPARAM lParam) +{ + if ( message == wxWM_PROC_TERMINATED ) + { +// DestroyWindow(hWnd); // we don't need it any more + + wxExecuteData *data = (wxExecuteData *)lParam; + if ( data->handler ) + { + data->handler->OnTerminate((int)data->dwProcessId, + (int)data->dwExitCode); + } + + if ( data->state ) + { + // we're executing synchronously, tell the waiting thread + // that the process finished + data->state = 0; + } + else + { + // asynchronous execution - we should do the clean up + delete data; + } + } + + return 0; +} + +extern wxChar wxPanelClassName[]; long wxExecute(const wxString& command, bool sync, wxProcess *handler) { - // TODO + wxCHECK_MSG( !!command, 0, wxT("empty command in wxExecute") ); + + // the old code is disabled because we really need a process handle + // if we want to execute it asynchronously or even just get its + // return code and for this we must use CreateProcess() and not + // ShellExecute() + + // create the process +// TODO: +/* + STARTUPINFO si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + + PROCESS_INFORMATION pi; + + if ( ::CreateProcess( + NULL, // application name (use only cmd line) + (wxChar *)command.c_str(), // full command line + NULL, // security attributes: defaults for both + NULL, // the process and its main thread + FALSE, // don't inherit handles + CREATE_DEFAULT_ERROR_MODE, // flags + NULL, // environment (use the same) + NULL, // current directory (use the same) + &si, // startup info (unused here) + &pi // process info + ) == 0 ) + { + wxLogSysError(_("Execution of command '%s' failed"), command.c_str()); + + return 0; + } + + // close unneeded handle + if ( !::CloseHandle(pi.hThread) ) + wxLogLastError("CloseHandle(hThread)"); + + // create a hidden window to receive notification about process + // termination + HWND hwnd = ::CreateWindow(wxPanelClassName, NULL, 0, 0, 0, 0, 0, NULL, + (HMENU)NULL, wxGetInstance(), 0); + wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") ); + + FARPROC ExecuteWindowInstance = MakeProcInstance((FARPROC)wxExecuteWindowCbk, + wxGetInstance()); + + ::SetWindowLong(hwnd, GWL_WNDPROC, (LONG) ExecuteWindowInstance); + + // Alloc data + wxExecuteData *data = new wxExecuteData; + data->hProcess = pi.hProcess; + data->dwProcessId = pi.dwProcessId; + data->hWnd = hwnd; + data->state = sync; + if ( sync ) + { + wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") ); + + data->handler = NULL; + } + else + { + // may be NULL or not + data->handler = handler; + } + + DWORD tid; + HANDLE hThread = ::CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)wxExecuteThread, + (void *)data, + 0, + &tid); + + if ( !hThread ) + { + wxLogLastError("CreateThread in wxExecute"); + + DestroyWindow(hwnd); + delete data; + + // the process still started up successfully... + return pi.dwProcessId; + } + + if ( !sync ) + { + // clean up will be done when the process terminates + + // return the pid + return pi.dwProcessId; + } + + // waiting until command executed + while ( data->state ) + wxYield(); + + DWORD dwExitCode = data->dwExitCode; + delete data; + + // return the exit code + return dwExitCode; +*/ return 0; } + +long wxExecute(char **argv, bool sync, wxProcess *handler) +{ + wxString command; + + while ( *argv != NULL ) + { + command << *argv++ << ' '; + } + + command.RemoveLast(); + + return wxExecute(command, sync, handler); +} + +bool wxGetFullHostName(wxChar *buf, int maxSize) +{ + DWORD nSize = maxSize ; +// TODO: +/* + if ( !::GetComputerName(buf, &nSize) ) + { + wxLogLastError("GetComputerName"); + + return FALSE; + } +*/ + return TRUE; +} + diff --git a/src/os2/wave.cpp b/src/os2/wave.cpp index c25681858c..bf21d37303 100644 --- a/src/os2/wave.cpp +++ b/src/os2/wave.cpp @@ -1,21 +1,33 @@ ///////////////////////////////////////////////////////////////////////////// // Name: wave.cpp // Purpose: wxWave class implementation: optional -// Author: AUTHOR +// Author: David Webster // Modified by: -// Created: ??/??/98 +// Created: 10/17/99 // RCS-ID: $Id$ -// Copyright: (c) AUTHOR -// Licence: wxWindows licence +// Copyright: (c) David Webster +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "wave.h" +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifndef WX_PRECOMP +#include "wx/wx.h" #endif -#include "wx/object.h" -#include "wx/string.h" -#include "wx/stubs/wave.h" +#include "wx/file.h" +#include "wx/os2/wave.h" +#include "wx/os2/private.h" + +#define INCL_DOS +#define INCL_PM +#include +#ifdef RECT + #undef RECT +#endif +#include +#include wxWave::wxWave() : m_waveData(NULL), m_waveLength(0), m_isResource(FALSE) @@ -23,39 +35,122 @@ wxWave::wxWave() } wxWave::wxWave(const wxString& sFileName, bool isResource) - : m_waveData(NULL), m_waveLength(0), m_isResource(FALSE) + : m_waveData(NULL), m_waveLength(0), m_isResource(isResource) { - Create(sFileName, isResource); + Create(sFileName, isResource); } +wxWave::wxWave(int size, const wxByte* data) + : m_waveData(NULL), m_waveLength(0), m_isResource(FALSE) +{ + Create(size, data); +} wxWave::~wxWave() { - Free(); + Free(); } bool wxWave::Create(const wxString& fileName, bool isResource) { - Free(); + Free(); - // TODO + if (isResource) + { + m_isResource = TRUE; +// TODO: +/* + HRSRC hresInfo; +#ifdef _UNICODE + hresInfo = ::FindResourceW((HMODULE) wxhInstance, fileName, wxT("WAVE")); +#else + hresInfo = ::FindResourceA((HMODULE) wxhInstance, fileName, wxT("WAVE")); +#endif + if (!hresInfo) + return FALSE; + + HGLOBAL waveData = ::LoadResource((HMODULE) wxhInstance, hresInfo); + + if (waveData) + { + m_waveData= (wxByte*)::LockResource(waveData); + m_waveLength = (int) ::SizeofResource((HMODULE) wxhInstance, hresInfo); + } + return (m_waveData ? TRUE : FALSE); +*/ return FALSE; + } + else + { + m_isResource = FALSE; + + wxFile fileWave; + if (!fileWave.Open(fileName, wxFile::read)) + return FALSE; + + m_waveLength = (int) fileWave.Length(); +// TODO: +/* + m_waveData = (wxByte*)::GlobalLock(::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, m_waveLength)); + if (!m_waveData) + return FALSE; + + fileWave.Read(m_waveData, m_waveLength); +*/ + return TRUE; + } } -bool wxWave::Play(bool async, bool looped) const +bool wxWave::Create(int size, const wxByte* data) { - if (!IsOk()) - return FALSE; + Free(); + m_isResource = FALSE; + m_waveLength=size; + m_waveData = NULL; // (wxByte*)::GlobalLock(::GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, m_waveLength)); + if (!m_waveData) + return FALSE; - // TODO - return FALSE; + for (int i=0; i