From f97c985452b20a8c2f0bbfb1d0275298bf09fb45 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Mon, 28 Sep 1998 15:42:54 +0000 Subject: [PATCH] More wxMotif work, OGL enhancements, USE_ macro corrections, object.cpp delete operator correction for VC++ 6 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@780 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/defs.h | 3 + include/wx/gdicmn.h | 3 +- include/wx/motif/bitmap.h | 47 ++- include/wx/motif/choice.h | 21 +- include/wx/motif/cursor.h | 35 +- include/wx/motif/font.h | 38 +- include/wx/motif/icon.h | 50 +-- include/wx/motif/listbox.h | 11 +- include/wx/motif/palette.h | 25 +- include/wx/msw/checklst.h | 2 +- include/wx/msw/ole/dropsrc.h | 2 +- include/wx/msw/ole/droptgt.h | 2 +- src/common/docview.cpp | 11 +- src/common/memory.cpp | 30 +- src/common/object.cpp | 2 +- src/make.env | 14 +- src/motif/app.cpp | 2 + src/motif/bitmap.cpp | 602 +++++++++++++++++++++++++++++-- src/motif/choice.cpp | 330 ++++++++++++++++- src/motif/cursor.cpp | 480 ++++++++++++++++++------- src/motif/dcclient.cpp | 10 +- src/motif/filedlg.cpp | 172 +++++++++ src/motif/font.cpp | 65 ++-- src/motif/icon.cpp | 25 +- src/motif/listbox.cpp | 642 ++++++++++++++++++++++++++++++---- src/motif/palette.cpp | 281 ++++++++++++++- src/motif/region.cpp | 92 +++-- src/motif/window.cpp | 98 +++--- src/msw/makefile.nt | 10 +- src/msw/tbarmsw.cpp | 2 +- src/msw/xfspline.inc | 12 +- src/stubs/cursor.cpp | 4 +- utils/ogl/src/basic.cpp | 435 ++++++++++++++++++++++- utils/ogl/src/basic.h | 87 ++++- utils/ogl/src/basic2.cpp | 72 +--- utils/ogl/src/divided.cpp | 2 +- utils/ogl/src/drawn.cpp | 4 +- utils/ogl/src/drawnp.h | 4 +- utils/ogl/src/lines.cpp | 14 +- utils/ogl/src/lines.h | 6 +- utils/ogl/src/makefile.nt | 26 +- utils/ogl/src/ogldiag.cpp | 160 +++++++++ utils/ogl/src/ogldiag.h | 27 ++ utils/wxprop/src/proplist.cpp | 63 +++- 44 files changed, 3424 insertions(+), 599 deletions(-) diff --git a/include/wx/defs.h b/include/wx/defs.h index 13c94ff050..888a5b0cc6 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -902,6 +902,9 @@ typedef void* WXFontStructPtr; typedef void* WXGC; typedef void* WXRegion; typedef void* WXFont; +typedef void* WXImage; +typedef void* WXCursor; +typedef void* WXFontList; #endif #endif diff --git a/include/wx/gdicmn.h b/include/wx/gdicmn.h index d726d44c1e..49cbec5448 100644 --- a/include/wx/gdicmn.h +++ b/include/wx/gdicmn.h @@ -25,6 +25,7 @@ // Standard cursors typedef enum { + wxCURSOR_NONE = 0, wxCURSOR_ARROW = 1, wxCURSOR_BULLSEYE, wxCURSOR_CHAR, @@ -57,7 +58,7 @@ typedef enum { wxCURSOR_BASED_ARROW_UP, wxCURSOR_BASED_ARROW_DOWN #endif -} _standard_cursors_t; +} wxStockCursor; class WXDLLEXPORT wxSize { diff --git a/include/wx/motif/bitmap.h b/include/wx/motif/bitmap.h index 4fec4f62c1..9c60d94c91 100644 --- a/include/wx/motif/bitmap.h +++ b/include/wx/motif/bitmap.h @@ -55,6 +55,7 @@ public: bool Create(const wxBitmap& bitmap); inline WXPixmap GetPixmap() const { return m_pixmap; } + inline void SetPixmap(WXPixmap pixmap) { m_pixmap = pixmap; } protected: WXPixmap m_pixmap; @@ -70,20 +71,30 @@ public: ~wxBitmapRefData(); public: - int m_width; - int m_height; - int m_depth; - bool m_ok; - int m_numColors; - wxPalette m_bitmapPalette; - int m_quality; + int m_width; + int m_height; + int m_depth; + bool m_ok; + int m_numColors; + wxPalette m_bitmapPalette; + int m_quality; - wxMask * m_bitmapMask; // Optional mask + wxMask * m_bitmapMask; // Optional mask // Motif implementation public: - WXPixmap m_pixmap; - WXDisplay* m_display; + WXPixmap m_pixmap; + WXDisplay* m_display; + bool m_freePixmap; + unsigned long* m_freeColors; + long m_freeColorsCount; + + // These 5 variables are for wxControl + WXPixmap m_insensPixmap ; + WXPixmap m_labelPixmap ; + WXPixmap m_armPixmap ; + WXImage* m_image ; + WXImage* m_insensImage ; }; #define M_BITMAPDATA ((wxBitmapRefData *)m_refData) @@ -127,17 +138,14 @@ public: { Ref(bitmap); if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this); } inline wxBitmap(const wxBitmap* bitmap) { if (bitmap) Ref(*bitmap); if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this); } - // Initialize with raw data. + // Initialize with raw XBM data wxBitmap(const char bits[], int width, int height, int depth = 1); -/* TODO: maybe implement XPM reading // Initialize with XPM data - wxBitmap(const char **data); -*/ + wxBitmap(const char **data, wxControl* control = NULL); // Load a file or resource - // TODO: make default type whatever's appropriate for the platform. - wxBitmap(const wxString& name, long type = wxBITMAP_TYPE_BMP_RESOURCE); + wxBitmap(const wxString& name, long type = wxBITMAP_TYPE_XBM); // Constructor for generalised creation from data wxBitmap(void *data, long type, int width, int height, int depth = 1); @@ -148,7 +156,7 @@ public: virtual bool Create(int width, int height, int depth = -1); virtual bool Create(void *data, long type, int width, int height, int depth = 1); - virtual bool LoadFile(const wxString& name, long type = wxBITMAP_TYPE_BMP_RESOURCE); + virtual bool LoadFile(const wxString& name, long type = wxBITMAP_TYPE_XBM); virtual bool SaveFile(const wxString& name, int type, const wxPalette *cmap = NULL); inline bool Ok() const { return (M_BITMAPDATA && M_BITMAPDATA->m_ok); } @@ -188,11 +196,12 @@ public: public: inline WXDisplay* GetDisplay() const { return M_BITMAPDATA->m_display; } inline WXDisplay* GetPixmap() const { return M_BITMAPDATA->m_pixmap; } + virtual WXPixmap GetLabelPixmap(WXWidget w) ; + virtual WXPixmap GetArmPixmap(WXWidget w) ; + virtual WXPixmap GetInsensPixmap(WXWidget w) ; protected: static wxList sm_handlers; - - }; #endif // _WX_BITMAP_H_ diff --git a/include/wx/motif/choice.h b/include/wx/motif/choice.h index 7db33d7ad4..30423c0e96 100644 --- a/include/wx/motif/choice.h +++ b/include/wx/motif/choice.h @@ -26,7 +26,8 @@ class WXDLLEXPORT wxChoice: public wxControl DECLARE_DYNAMIC_CLASS(wxChoice) public: - inline wxChoice() { m_noStrings = 0; } + wxChoice(); + ~wxChoice(); inline wxChoice(wxWindow *parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition, @@ -61,11 +62,23 @@ class WXDLLEXPORT wxChoice: public wxControl virtual inline int Number() const { return m_noStrings; } virtual void Command(wxCommandEvent& event); - virtual inline void SetColumns(int WXUNUSED(n) = 1 ) { /* No effect */ } ; - virtual inline int GetColumns() const { return 1 ; }; + virtual void SetColumns(int n = 1 ); + virtual int GetColumns() const ; + + void SetFocus(); + + WXWidget GetTopWidget() const { return m_formWidget; } + WXWidget GetMainWidget() const { return m_buttonWidget; } protected: - int m_noStrings; + int m_noStrings; + WXWidget m_menuWidget; + WXWidget m_buttonWidget; + WXWidget* m_widgetList ; + WXWidget m_formWidget; + wxStringList m_stringList; +public: + bool m_inSetValue; }; #endif diff --git a/include/wx/motif/cursor.h b/include/wx/motif/cursor.h index 3db0a16fe7..0fde180335 100644 --- a/include/wx/motif/cursor.h +++ b/include/wx/motif/cursor.h @@ -18,6 +18,18 @@ #include "wx/bitmap.h" +/* Cursor for one display, so we can choose the correct one for + * the current display. + */ +class wxXCursor : public wxObject +{ + DECLARE_DYNAMIC_CLASS(wxXCursor) + + public: + WXDisplay* m_display; + WXCursor m_cursor; +}; + class WXDLLEXPORT wxCursorRefData: public wxBitmapRefData { friend class WXDLLEXPORT wxBitmap; @@ -26,10 +38,8 @@ public: wxCursorRefData(); ~wxCursorRefData(); -protected: -/* TODO: implementation - WXHCURSOR m_hCursor; -*/ + wxList m_cursors; // wxXCursor objects, one per display + wxStockCursor m_cursorId; // wxWindows standard cursor id }; #define M_CURSORDATA ((wxCursorRefData *)m_refData) @@ -50,24 +60,23 @@ public: wxCursor(const char bits[], int width, int height, int hotSpotX = -1, int hotSpotY = -1, const char maskBits[] = NULL); - /* TODO: make default type suit platform */ - wxCursor(const wxString& name, long flags = wxBITMAP_TYPE_CUR_RESOURCE, + wxCursor(const wxString& name, long flags = wxBITMAP_TYPE_XBM, int hotSpotX = 0, int hotSpotY = 0); - wxCursor(int cursor_type); + wxCursor(wxStockCursor id); ~wxCursor(); - // TODO: also verify the internal cursor handle - virtual bool Ok() const { return (m_refData != NULL) ; } + virtual bool Ok() const { return ((m_refData != NULL) && M_CURSORDATA->m_ok); } inline wxCursor& operator = (const wxCursor& cursor) { if (*this == cursor) return (*this); Ref(cursor); return *this; } inline bool operator == (const wxCursor& cursor) { return m_refData == cursor.m_refData; } inline bool operator != (const wxCursor& cursor) { return m_refData != cursor.m_refData; } -/* TODO: implementation - void SetHCURSOR(WXHCURSOR cursor); - inline WXHCURSOR GetHCURSOR() const { return (M_CURSORDATA ? M_CURSORDATA->m_hCursor : 0); } -*/ + // Motif-specific. + // Create/get a cursor for the current display + WXCursor GetXCursor(WXDisplay* display) ; + // Make a cursor from standard id + WXCursor MakeCursor(WXDisplay* display, wxStockCursor id); }; extern WXDLLEXPORT void wxSetCursor(const wxCursor& cursor); diff --git a/include/wx/motif/font.h b/include/wx/motif/font.h index b5149ef4dc..769b4d6352 100644 --- a/include/wx/motif/font.h +++ b/include/wx/motif/font.h @@ -21,6 +21,20 @@ class WXDLLEXPORT wxFont; +// For every wxFont, there must be a font for each display and scale requested. +// So these objects are stored in wxFontRefData::m_fonts +class WXDLLEXPORT wxXFont: public wxObject +{ +public: + wxXFont(); + ~wxXFont(); + + WXFontStructPtr m_fontStruct; // XFontStruct + WXFontList m_fontList; // Motif XmFontList + WXDisplay* m_display; // XDisplay + int m_scale; // Scale * 100 +}; + class WXDLLEXPORT wxFontRefData: public wxGDIRefData { friend class WXDLLEXPORT wxFont; @@ -36,8 +50,8 @@ protected: bool m_underlined; wxString m_faceName; - // A list of XFontStructs indexed by scale (*100) - wxList m_fontsByScale; + // A list of wxXFonts + wxList m_fonts; }; #define M_FONTDATA ((wxFontRefData *)m_refData) @@ -87,16 +101,30 @@ public: // based on this wxFont and the given scale. Append the // font to list in the private data for future reference. - // TODO This is a very basic implementation, that doesn't + // TODO This is a fairly basic implementation, that doesn't // allow for different facenames, and also doesn't do a mapping // between 'standard' facenames (e.g. Arial, Helvetica, Times Roman etc.) // and the fonts that are available on a particular system. // Maybe we need to scan the user's machine to build up a profile // of the fonts and a mapping file. - WXFontStructPtr FindOrCreateFontStruct(double scale = 1.0); + // Return font struct, and optionally the Motif font list + wxXFont* GetInternalFont(double scale = 1.0, WXDisplay* display = NULL) const; + + // These two are helper functions for convenient access of the above. + inline WXFontStructPtr GetFontStruct(double scale = 1.0, WXDisplay* display = NULL) const + { + wxXFont* f = GetInternalFont(scale, display); + return (f ? f->m_fontStruct : (WXFontStructPtr) 0); + } + WXFontList GetFontList(double scale = 1.0, WXDisplay* display = NULL) const + { + wxXFont* f = GetInternalFont(scale, display); + return (f ? f->m_fontList : (WXFontList) 0); + } + WXFontStructPtr LoadQueryFont(int pointSize, int family, int style, - int weight, bool underlined); + int weight, bool underlined) const; protected: bool RealizeResource(); void Unshare(); diff --git a/include/wx/motif/icon.h b/include/wx/motif/icon.h index 012fd0754d..92eb0eccfc 100644 --- a/include/wx/motif/icon.h +++ b/include/wx/motif/icon.h @@ -18,6 +18,8 @@ #include "wx/bitmap.h" +/* +// Same as for wxBitmap class WXDLLEXPORT wxIconRefData: public wxBitmapRefData { friend class WXDLLEXPORT wxBitmap; @@ -26,9 +28,10 @@ public: wxIconRefData(); ~wxIconRefData(); }; +*/ -#define M_ICONDATA ((wxIconRefData *)m_refData) -#define M_ICONHANDLERDATA ((wxIconRefData *)bitmap->GetRefData()) +#define M_ICONDATA ((wxBitmapRefData *)m_refData) +#define M_ICONHANDLERDATA ((wxBitmapRefData *)bitmap->GetRefData()) // Icon class WXDLLEXPORT wxIcon: public wxBitmap @@ -42,7 +45,12 @@ public: inline wxIcon(const wxIcon& icon) { Ref(icon); } inline wxIcon(const wxIcon* icon) { if (icon) Ref(*icon); } + // Initialize with XBM data wxIcon(const char bits[], int width, int height); + + // Initialize with XPM data + wxIcon(const char **data); + wxIcon(const wxString& name, long flags = wxBITMAP_TYPE_ICO_RESOURCE, int desiredWidth = -1, int desiredHeight = -1); ~wxIcon(); @@ -54,44 +62,8 @@ public: inline bool operator == (const wxIcon& icon) { return m_refData == icon.m_refData; } inline bool operator != (const wxIcon& icon) { return m_refData != icon.m_refData; } -/* TODO */ - virtual bool Ok() const { return (m_refData != NULL) ; } -}; - -/* Example handlers. TODO: write your own handlers for relevant types. - -class WXDLLEXPORT wxICOFileHandler: public wxBitmapHandler -{ - DECLARE_DYNAMIC_CLASS(wxICOFileHandler) -public: - inline wxICOFileHandler() - { - m_name = "ICO icon file"; - m_extension = "ico"; - m_type = wxBITMAP_TYPE_ICO; - }; - - virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, - int desiredWidth = -1, int desiredHeight = -1); + virtual bool Ok() const { return ((m_refData != NULL) && (M_ICONDATA->m_ok)); } }; -class WXDLLEXPORT wxICOResourceHandler: public wxBitmapHandler -{ - DECLARE_DYNAMIC_CLASS(wxICOResourceHandler) -public: - inline wxICOResourceHandler() - { - m_name = "ICO resource"; - m_extension = "ico"; - m_type = wxBITMAP_TYPE_ICO_RESOURCE; - }; - - virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, - int desiredWidth = -1, int desiredHeight = -1); - -}; - -*/ - #endif // _WX_ICON_H_ diff --git a/include/wx/motif/listbox.h b/include/wx/motif/listbox.h index 5ba7762189..5ca22a7d03 100644 --- a/include/wx/motif/listbox.h +++ b/include/wx/motif/listbox.h @@ -38,7 +38,8 @@ class WXDLLEXPORT wxListBox: public wxControl int n = 0, const wxString choices[] = NULL, long style = 0, const wxValidator& validator = wxDefaultValidator, - const wxString& name = wxListBoxNameStr) + const wxString& name = wxListBoxNameStr): + m_clientDataList(wxKEY_INTEGER) { Create(parent, id, pos, size, n, choices, style, validator, name); } @@ -88,9 +89,15 @@ class WXDLLEXPORT wxListBox: public wxControl void Command(wxCommandEvent& event); - protected: +protected: int m_noItems; int m_selected; + + // List mapping positions->client data + wxList m_clientDataList; + +public: + bool m_inSetValue; }; #endif diff --git a/include/wx/motif/palette.h b/include/wx/motif/palette.h index 4bc644cb7f..589b7735e0 100644 --- a/include/wx/motif/palette.h +++ b/include/wx/motif/palette.h @@ -17,9 +17,25 @@ #endif #include "wx/gdiobj.h" +#include "wx/list.h" class WXDLLEXPORT wxPalette; +// Palette for one display +class wxXPalette : public wxObject +{ +DECLARE_DYNAMIC_CLASS(wxXPalette) + +public: + wxXPalette(); + + WXDisplay* m_display; + int m_pix_array_n; + unsigned long* m_pix_array; + WXColormap m_cmap; + bool m_destroyable; +}; + class WXDLLEXPORT wxPaletteRefData: public wxGDIRefData { friend class WXDLLEXPORT wxPalette; @@ -28,7 +44,7 @@ public: ~wxPaletteRefData(); protected: - WXColormap m_colormap; + wxList m_palettes; }; #define M_PALETTEDATA ((wxPaletteRefData *)m_refData) @@ -54,7 +70,12 @@ public: inline bool operator == (const wxPalette& palette) { return m_refData == palette.m_refData; } inline bool operator != (const wxPalette& palette) { return m_refData != palette.m_refData; } - WXColormap GetXColormap() const { return (M_PALETTEDATA->m_colormap); } + // Motif-specific + WXColormap GetXColormap(WXDisplay* display = NULL) const; + bool TransferBitmap(void *data, int depth, int size); + bool TransferBitmap8(unsigned char *data, unsigned long size, void *dest, unsigned int bpp); + unsigned long *GetXPixArray(WXDisplay* display, int *pix_array_n); + void PutXColormap(WXDisplay* display, WXColormap cmap, bool destroyable); }; #endif diff --git a/include/wx/msw/checklst.h b/include/wx/msw/checklst.h index 163291f121..a58714daa6 100644 --- a/include/wx/msw/checklst.h +++ b/include/wx/msw/checklst.h @@ -18,7 +18,7 @@ typedef unsigned int size_t; -#if !USE_OWNER_DRAWN +#if !wxUSE_OWNER_DRAWN #error "wxCheckListBox class requires owner-drawn functionality." #endif diff --git a/include/wx/msw/ole/dropsrc.h b/include/wx/msw/ole/dropsrc.h index 4ed544cf38..a36324a994 100644 --- a/include/wx/msw/ole/dropsrc.h +++ b/include/wx/msw/ole/dropsrc.h @@ -16,7 +16,7 @@ #pragma interface #endif -#if !USE_DRAG_AND_DROP +#if !wxUSE_DRAG_AND_DROP #error "You should #define wxUSE_DRAG_AND_DROP to 1 to compile this file!" #endif //WX_DRAG_DROP diff --git a/include/wx/msw/ole/droptgt.h b/include/wx/msw/ole/droptgt.h index 065d56c63f..95484cf7a6 100644 --- a/include/wx/msw/ole/droptgt.h +++ b/include/wx/msw/ole/droptgt.h @@ -19,7 +19,7 @@ #pragma interface "droptgt.h" #endif -#if !USE_DRAG_AND_DROP +#if !wxUSE_DRAG_AND_DROP #error "You should #define wxUSE_DRAG_AND_DROP to 1 to compile this file!" #endif //WX_DRAG_DROP diff --git a/src/common/docview.cpp b/src/common/docview.cpp index 81ec15a123..2ab0f4cd24 100644 --- a/src/common/docview.cpp +++ b/src/common/docview.cpp @@ -1639,7 +1639,16 @@ bool wxCommandProcessor::CanUndo(void) const bool wxCommandProcessor::CanRedo(void) const { - return ((m_currentCommand && m_currentCommand->Next())); + if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() == (wxNode*) NULL)) + return FALSE; + + if ((m_currentCommand != (wxNode*) NULL) && (m_currentCommand->Next() != (wxNode*) NULL)) + return TRUE; + + if ((m_currentCommand == (wxNode*) NULL) && (m_commands.Number() > 0)) + return TRUE; + + return FALSE; } void wxCommandProcessor::Initialize(void) diff --git a/src/common/memory.cpp b/src/common/memory.cpp index 304e9ce1ec..d3771ff98c 100644 --- a/src/common/memory.cpp +++ b/src/common/memory.cpp @@ -324,7 +324,7 @@ void wxMemStruct::PrintNode () { wxObject *obj = (wxObject *)m_actualData; wxClassInfo *info = obj->GetClassInfo(); - +/* if (info && info->GetClassName()) wxTrace("%s", info->GetClassName()); else @@ -333,13 +333,25 @@ void wxMemStruct::PrintNode () if (m_fileName) wxTrace(" (%s %d)", m_fileName, (int)m_lineNum); + wxTrace(" at $%lX, size %d\n", (long)GetActualData(), (int)RequestSize()); +*/ + // Let's put this in standard form so IDEs can load the file at the appropriate + // line + if (m_fileName) + wxTrace("%s(%d): ", m_fileName, (int)m_lineNum); + + if (info && info->GetClassName()) + wxTrace("%s", info->GetClassName()); + else + wxTrace("object"); + wxTrace(" at $%lX, size %d\n", (long)GetActualData(), (int)RequestSize()); } else { - wxTrace("Non-object data"); if (m_fileName) - wxTrace(" (%s %d)", m_fileName, (int)m_lineNum); + wxTrace("%s(%d): ", m_fileName, (int)m_lineNum); + wxTrace("non-object data"); wxTrace(" at $%lX, size %d\n", (long)GetActualData(), (int)RequestSize()); } } @@ -351,23 +363,19 @@ void wxMemStruct::Dump () if (m_isObject) { wxObject *obj = (wxObject *)m_actualData; -// wxClassInfo *info = obj->GetClassInfo(); if (m_fileName) - wxTrace("Item (%s %d)", m_fileName, (int)m_lineNum); - else - wxTrace("Item"); + wxTrace("%s(%d): ", m_fileName, (int)m_lineNum); - wxTrace(" at $%lX, size %d: ", (long)GetActualData(), (int)RequestSize()); -// wxTrace(info->GetClassName()); obj->Dump(wxDebugContext::GetStream()); + wxTrace(" at $%lX, size %d", (long)GetActualData(), (int)RequestSize()); wxTrace("\n"); } else { - wxTrace("Non-object data"); if (m_fileName) - wxTrace(" (%s %d)", m_fileName, (int)m_lineNum); + wxTrace("%s(%d): ", m_fileName, (int)m_lineNum); + wxTrace("non-object data"); wxTrace(" at $%lX, size %d\n", (long)GetActualData(), (int)RequestSize()); } } diff --git a/src/common/object.cpp b/src/common/object.cpp index d5afed37de..d26826ebe2 100644 --- a/src/common/object.cpp +++ b/src/common/object.cpp @@ -111,7 +111,7 @@ void wxObject::operator delete (void * buf) // VC++ 6.0 #if _MSC_VER >= 1200 -void operator delete(void* pData, char* /* fileName */, int /* lineNum */) +void operator wxObject::delete(void* pData, char* /* fileName */, int /* lineNum */) { ::operator delete(pData); } diff --git a/src/make.env b/src/make.env index a5a1a2d4a1..874f37ec13 100644 --- a/src/make.env +++ b/src/make.env @@ -5,17 +5,6 @@ # This file is included by all the other makefiles, thus changes # made here take effect everywhere (except where overriden). # -# An alternative to editing this file is to create a shell script -# to export specific variables, and call make with the -e switch -# to override makefile variables. See wx/install/install.txt. -# And you can override specific variables on the make command line, e.g. -# -# make -f makefile.unix DEBUG='' -# -# You may prefer to use the GNU configure script than raw makefiles - -# see contrib/wxshlib. -# - ########################### Programs ################################# # Replace this with your own path if necessary @@ -110,6 +99,9 @@ stubs: motif: make -f makefile.unx all GUI='-D__WXMOTIF__ -D__LINUX__ -D__UNIX__' GUISUFFIX='_motif' GUILDLIBS='-lwx_motif $(COMPLIBS) -lXm -lXmu -lXt -lX11 -lm' +gtk: + make -f makefile.unx all GUI='-D__WXGTK__ -D__LINUX__ -D__UNIX__' GUISUFFIX='_gtk' GUILDLIBS='-lwx_gtk $(COMPLIBS) -lXm -lXmu -lX11 -lm' + cleanstubs: make -f makefile.unx clean GUI='-D__WXSTUBS__ -D__LINUX__ -D__UNIX__' GUISUFFIX='_stubs' GUILDLIBS='-lwx_stubs $(COMPLIBS) -lXm -lXmu -lXt -lX11 -lm' diff --git a/src/motif/app.cpp b/src/motif/app.cpp index d8df53ed4c..df82c80919 100644 --- a/src/motif/app.cpp +++ b/src/motif/app.cpp @@ -296,6 +296,8 @@ int wxApp::MainLoop() report = event; while( XCheckTypedWindowEvent (disp, win, ResizeRequest, &report)); } + // TODO: when implementing refresh optimization, we can use + // XtAddExposureToRegion to expand the window's paint region. XtDispatchEvent(&event); diff --git a/src/motif/bitmap.cpp b/src/motif/bitmap.cpp index 865b319997..58b53da7f7 100644 --- a/src/motif/bitmap.cpp +++ b/src/motif/bitmap.cpp @@ -20,6 +20,15 @@ #include "wx/icon.h" #include "wx/log.h" +#include + +#include "wx/motif/private.h" + +// TODO: correct symbol, path? +#if USE_XPM +#include +#endif + #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject) IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject) @@ -37,13 +46,54 @@ wxBitmapRefData::wxBitmapRefData() m_pixmap = (WXPixmap) 0; m_display = (WXDisplay*) 0; + + m_freePixmap = TRUE; //TODO: necessary? + m_freeColors = (unsigned long*) 0; + m_freeColorsCount = 0; + + // These 5 variables are for wxControl + m_insensPixmap = (WXPixmap) 0; + m_labelPixmap = (WXPixmap) 0; + m_armPixmap = (WXPixmap) 0; + m_image = (WXImage*) 0; + m_insensImage = (WXImage*) 0; } wxBitmapRefData::~wxBitmapRefData() { - /* - * TODO: delete the bitmap data here. - */ + if (m_labelPixmap) + XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap); + + if (m_armPixmap) + XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap); + + if (m_insensPixmap) + XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap); + + if (m_image) + { + XmUninstallImage ((XImage*) m_image); + XtFree ((char *) (XImage*) m_image); + } + + if (m_insensImage) + { + XmUninstallImage ((XImage*) m_insensImage); + delete[] ((XImage*) m_insensImage)->data; + XtFree ((char *) (XImage*) m_insensImage); + } + if (m_pixmap && m_freePixmap) + XFreePixmap ((Display*) m_display, (Pixmap) m_pixmap); + + if (m_freeColors) + { + int screen = DefaultScreen((Display*) m_display); + Colormap cmp = DefaultColormap((Display*) m_display,screen); + long llp; + for(llp = 0;llp < m_freeColorsCount;llp++) + XFreeColors((Display*) m_display, cmp, &m_freeColors[llp], 1, 0L); + delete m_freeColors; + }; if (m_bitmapMask) delete m_bitmapMask; @@ -66,16 +116,11 @@ wxBitmap::~wxBitmap() wxTheBitmapList->DeleteObject(this); } -wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits) +wxBitmap::wxBitmap(const char bits[], int width, int height, int depth) { m_refData = new wxBitmapRefData; - M_BITMAPDATA->m_width = the_width ; - M_BITMAPDATA->m_height = the_height ; - M_BITMAPDATA->m_depth = no_bits ; - M_BITMAPDATA->m_numColors = 0; - - /* TODO: create the bitmap from data */ + (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth); if ( wxTheBitmapList ) wxTheBitmapList->AddBitmap(this); @@ -105,13 +150,17 @@ wxBitmap::wxBitmap(const wxString& filename, long type) wxTheBitmapList->AddBitmap(this); } -/* TODO: maybe allow creation from XPM -// Create from data -wxBitmap::wxBitmap(const char **data) +// Create from XPM data +static wxControl* sg_Control = NULL; +wxBitmap::wxBitmap(const char **data, wxControl* control) { + // Pass the control to the Create function using a global + sg_Control = control; + (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); + + sg_Control = (wxControl*) NULL; } -*/ bool wxBitmap::Create(int w, int h, int d) { @@ -119,12 +168,22 @@ bool wxBitmap::Create(int w, int h, int d) m_refData = new wxBitmapRefData; + if (d < 1) + d = wxDisplayDepth(); + M_BITMAPDATA->m_width = w; M_BITMAPDATA->m_height = h; M_BITMAPDATA->m_depth = d; + M_BITMAPDATA->m_freePixmap = TRUE; - /* TODO: create new bitmap */ + Display *dpy = (Display*) wxGetDisplay(); + M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */ + + M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)), + w, h, d); + + M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ; return M_BITMAPDATA->m_ok; } @@ -330,7 +389,9 @@ wxMask::wxMask(const wxBitmap& bitmap) wxMask::~wxMask() { -// TODO: delete mask bitmap + // TODO: this may be the wrong display + if ( m_pixmap ) + XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap); } // Create a mask from a mono bitmap (copies the bitmap). @@ -382,23 +443,301 @@ bool wxBitmapHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, * Standard handlers */ -/* TODO: bitmap handlers, a bit like this: -class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler +class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler { - DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler) + DECLARE_DYNAMIC_CLASS(wxXBMFileHandler) public: - inline wxBMPResourceHandler() + inline wxXBMFileHandler() { - m_name = "Windows bitmap resource"; - m_extension = ""; - m_type = wxBITMAP_TYPE_BMP_RESOURCE; + m_name = "XBM file"; + m_extension = "xbm"; + m_type = wxBITMAP_TYPE_XBM; }; virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, int desiredWidth, int desiredHeight); }; -IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler) -*/ +IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler) + +bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ + M_BITMAPHANDLERDATA->m_freePixmap = TRUE; + + int hotX, hotY; + unsigned int w, h; + Pixmap pixmap; + + Display *dpy = (Display*) wxGetDisplay(); + M_BITMAPDATA->m_display = (WXDisplay*) dpy; + + int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)), + (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY); + M_BITMAPHANDLERDATA->m_width = w; + M_BITMAPHANDLERDATA->m_height = h; + M_BITMAPHANDLERDATA->m_depth = 1; + M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; + + if ((value == BitmapFileInvalid) || + (value == BitmapOpenFailed) || + (value == BitmapNoMemory)) + { + M_BITMAPHANDLERDATA->m_ok = FALSE; + M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) 0; + } + else + M_BITMAPHANDLERDATA->m_ok = TRUE; + + return M_BITMAPHANDLERDATA->m_ok ; +} + +class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxXBMDataHandler) +public: + inline wxXBMDataHandler() + { + m_name = "XBM data"; + m_extension = "xbm"; + m_type = wxBITMAP_TYPE_XBM_DATA; + }; + + virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1); +}; +IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler) + +bool wxXBMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth) +{ + M_BITMAPHANDLERDATA->m_width = width; + M_BITMAPHANDLERDATA->m_height = height; + M_BITMAPHANDLERDATA->m_depth = 1; + M_BITMAPHANDLERDATA->m_freePixmap = TRUE; + + Display *dpy = (Display*) wxGetDisplay(); + M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; + + M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), (char*) data, width, height); + M_BITMAPHANDLERDATA->m_ok = (M_BITMAPHANDLERDATA->m_pixmap != (WXPixmap) 0) ; + + // code for wxControl. TODO: can we avoid doing this until we need it? + // E.g. have CreateButtonPixmaps which is called on demand. + XImage* image = (XImage *) XtMalloc (sizeof (XImage)); + image->width = width; + image->height = height; + image->data = (char*) data; + image->depth = 1; + image->xoffset = 0; + image->format = XYBitmap; + image->byte_order = LSBFirst; + image->bitmap_unit = 8; + image->bitmap_bit_order = LSBFirst; + image->bitmap_pad = 8; + image->bytes_per_line = (width + 7) >> 3; + + char tmp[128]; + sprintf (tmp, "Im%x", (unsigned int) image); + XmInstallImage (image, tmp); + + // Build our manually stipped pixmap. + + int bpl = (width + 7) / 8; + char *data1 = new char[height * bpl]; + char* bits = (char*) data; + int i; + for (i = 0; i < height; i++) + { + int mask = i % 2 ? 0x55 : 0xaa; + int j; + for (j = 0; j < bpl; j++) + data1[i * bpl + j] = bits[i * bpl + j] & mask; + } + XImage* insensImage = (XImage *) XtMalloc (sizeof (XImage)); + insensImage->width = width; + insensImage->height = height; + insensImage->data = data1; + insensImage->depth = 1; + insensImage->xoffset = 0; + insensImage->format = XYBitmap; + insensImage->byte_order = LSBFirst; + insensImage->bitmap_unit = 8; + insensImage->bitmap_bit_order = LSBFirst; + insensImage->bitmap_pad = 8; + insensImage->bytes_per_line = bpl; + + sprintf (tmp, "Not%x", (unsigned int)insensImage); + XmInstallImage (insensImage, tmp); + + M_BITMAPHANDLERDATA->m_image = (WXImage*) image; + M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage; + + return TRUE; +} + +#if USE_XPM +class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxXPMFileHandler) +public: + inline wxXPMFileHandler() + { + m_name = "XPM file"; + m_extension = "xpm"; + m_type = wxBITMAP_TYPE_XPM; + }; + + virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight); + virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL); +}; + +IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler) + +bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long flags, + int desiredWidth, int desiredHeight) +{ + Display *dpy = wxGetDisplay(); + M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; + + XpmAttributes xpmAttr; + Pixmap pixmap; + Pixmap mask = 0; + + M_BITMAPHANDLERDATA->m_ok = FALSE; + xpmAttr.valuemask = XpmReturnInfos | XpmCloseness; + xpmAttr.closeness = 40000; + int errorStatus = XpmReadFileToPixmap(dpy, + RootWindow(dpy, DefaultScreen(dpy)), (char*) (const char*) name, + &pixmap, &mask, &xpmAttr); + + if (errorStatus == XpmSuccess) + { + M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; + if ( mask ) + { + M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask; + M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask); + } + + M_BITMAPHANDLERDATA->m_width = xpmAttr.width; + M_BITMAPHANDLERDATA->m_height = xpmAttr.height; + if ( xpmAttr.npixels > 2 ) + { + M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ... + } else + { + M_BITMAPHANDLERDATA->m_depth = 1; // mono + } + + M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; + + XpmFreeAttributes(&xpmAttr); + + M_BITMAPHANDLERDATA->m_ok = TRUE; + } else + { +// XpmDebugError(errorStatus, name); + M_BITMAPHANDLERDATA->m_ok = FALSE; + return FALSE; + } +} + +bool wxXPMFileHandler::SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette) +{ + if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap) + { + Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display; + int errorStatus = XpmWriteFileFromPixmap(dpy, (char*) (const char*) name, + (Pixmap) M_BITMAPHANDLERDATA->m_pixmap, + (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0), + (XpmAttributes *) NULL); + if (errorStatus == XpmSuccess) + return TRUE; + else + return FALSE; + } + else + return FALSE; +} + +class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler +{ + DECLARE_DYNAMIC_CLASS(wxXPMDataHandler) +public: + inline wxXBMDataHandler() + { + m_name = "XPM data"; + m_extension = "xpm"; + m_type = wxBITMAP_TYPE_XPM_DATA; + }; + + virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1); +}; +IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler) + +bool wxXPMDataHandler::Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth) +{ + M_BITMAPHANDLERDATA->m_width = width; + M_BITMAPHANDLERDATA->m_height = height; + M_BITMAPHANDLERDATA->m_depth = 1; + M_BITMAPHANDLERDATA->m_freePixmap = TRUE; + + Display *dpy = wxGetDisplay(); + M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy; + + XpmAttributes xpmAttr; + + xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */ + + XpmColorSymbol symbolicColors[4]; + if (sg_Control && sg_Control->GetMainWidget()) + { + symbolicColors[0].name = "foreground"; + symbolicColors[0].value = NULL; + symbolicColors[1].name = "background"; + symbolicColors[1].value = NULL; + XtVaGetValues((Widget) sg_Control->GetMainWidget(), + XmNforeground, &symbolicColors[0].pixel, + XmNbackground, &symbolicColors[1].pixel,NULL); + xpmAttr.numsymbols = 2; + xpmAttr.colorsymbols = symbolicColors; + xpmAttr.valuemask |= XpmColorSymbols; // add flag + } + + Pixmap pixmap; + Pixmap mask = 0; + int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)), + (char**) data, &pixmap, &mask, &xpmAttr); + if (ErrorStatus == XpmSuccess) + { + // Set attributes + M_BITMAPHANDLERDATA->m_width = xpmAttr.width; + M_BITMAPHANDLERDATA->m_height = xpmAttr.height; + if ( xpmAttr.npixels > 2 ) + { + M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ... + } else + { + M_BITMAPHANDLERDATA->m_depth = 1; // mono + } + M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels; + XpmFreeAttributes(&xpmAttr); + M_BITMAPHANDLERDATA->m_ok = TRUE; + M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap; + if ( mask ) + { + M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask; + M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask); + } + } + else + { +// XpmDebugError(ErrorStatus, NULL); + M_BITMAPHANDLERDATA->m_ok = FALSE; + } + return M_BITMAPHANDLERDATA->m_ok ; +} + +#endif void wxBitmap::CleanUpHandlers() { @@ -415,12 +754,213 @@ void wxBitmap::CleanUpHandlers() void wxBitmap::InitStandardHandlers() { -/* TODO: initialize all standard bitmap or derive class handlers here. - AddHandler(new wxBMPResourceHandler); - AddHandler(new wxBMPFileHandler); + // Initialize all standard bitmap or derived class handlers here. + AddHandler(new wxXBMFileHandler); + AddHandler(new wxXBMDataHandler); + + // XPM is considered standard for Moif, although it can be omitted if absolutely + // necessary. +#if USE_XPM AddHandler(new wxXPMFileHandler); AddHandler(new wxXPMDataHandler); - AddHandler(new wxICOResourceHandler); - AddHandler(new wxICOFileHandler); -*/ +#endif +} + +WXPixmap wxBitmap::GetLabelPixmap (WXWidget w) +{ + if (M_BITMAPDATA->m_image == (WXPixmap) 0) + return M_BITMAPDATA->m_pixmap; + + Display *dpy = (Display*) M_BITMAPDATA->m_display; + +#ifdef FOO +/* + If we do: + if (labelPixmap) return labelPixmap; + things can be wrong, because colors can have been changed. + + If we do: + if (labelPixmap) + XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ; + we got BadDrawable if the pixmap is referenced by multiples widgets + + this is a catch22!! + + So, before doing thing really clean, I just do nothing; if the pixmap is + referenced by many widgets, Motif performs caching functions. + And if pixmap is referenced with multiples colors, we just have some + memory leaks... I hope we can deal with them... + */ + // Must be destroyed, because colours can have been changed! + if (M_BITMAPDATA->m_labelPixmap) + XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap); +#endif + + char tmp[128]; + sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image); + + Pixel fg, bg; + Widget widget = (Widget) w; + + while (XmIsGadget ( widget )) + widget = XtParent (widget); + XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL); + + M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); + + return M_BITMAPDATA->m_labelPixmap; +} + +WXPixmap wxBitmap::GetArmPixmap (WXWidget w) +{ + if (M_BITMAPDATA->m_image == (WXPixmap) 0) + return M_BITMAPDATA->m_pixmap; + + Display *dpy = (Display*) M_BITMAPDATA->m_display; +#ifdef FOO + See GetLabelPixmap () comment + // Must be destroyed, because colours can have been changed! + if (M_BITMAPDATA->m_armPixmap) + XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap); +#endif + + char tmp[128]; + sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image); + + Pixel fg, bg; + Widget widget = (Widget) w; + + XtVaGetValues (widget, XmNarmColor, &bg, NULL); + while (XmIsGadget (widget)) + widget = XtParent (widget); + XtVaGetValues (widget, XmNforeground, &fg, NULL); + + M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); + + return M_BITMAPDATA->m_armPixmap; +} + +WXPixmap wxBitmap::GetInsensPixmap (WXWidget w) +{ + Display *dpy = (Display*) M_BITMAPDATA->m_display; + + if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0) + return M_BITMAPDATA->m_pixmap; + +#ifdef FOO + See GetLabelPixmap () comment + // Must be destroyed, because colours can have been changed! + if (M_BITMAPDATA->m_insensPixmap) + XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap); +#endif + + char tmp[128]; + sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage); + + Pixel fg, bg; + Widget widget = (Widget) w; + + while (XmIsGadget (widget)) + widget = XtParent (widget); + XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL); + + M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg); + + return M_BITMAPDATA->m_insensPixmap; +} + +// We may need this sometime... + +/**************************************************************************** + +NAME + XCreateInsensitivePixmap - create a grayed-out copy of a pixmap + +SYNOPSIS + Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap ) + +DESCRIPTION + This function creates a grayed-out copy of the argument pixmap, suitable + for use as a XmLabel's XmNlabelInsensitivePixmap resource. + +RETURN VALUES + The return value is the new Pixmap id or zero on error. Errors include + a NULL display argument or an invalid Pixmap argument. + +ERRORS + If one of the XLib functions fail, it will produce a X error. The + default X error handler prints a diagnostic and calls exit(). + +SEE ALSO + XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3), + XFillRectangle(3), exit(2) + +AUTHOR + John R Veregge - john@puente.jpl.nasa.gov + Advanced Engineering and Prototyping Group (AEG) + Information Systems Technology Section (395) + Jet Propulsion Lab - Calif Institute of Technology + +*****************************************************************************/ + +Pixmap +XCreateInsensitivePixmap( Display *display, Pixmap pixmap ) + +{ +static + char stipple_data[] = + { + 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, + 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, + 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, + 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA + }; + GC gc; + Pixmap ipixmap, stipple; + unsigned width, height, depth; + + Window window; /* These return values */ + unsigned border; /* from XGetGeometry() */ + int x, y; /* are not needed. */ + + ipixmap = 0; + + if ( NULL == display || 0 == pixmap ) + return ipixmap; + + if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y, + &width, &height, &border, &depth ) + ) + return ipixmap; /* BadDrawable: probably an invalid pixmap */ + + /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap. + */ + stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 ); + if ( 0 != stipple ) + { + gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL ); + if ( NULL != gc ) + { + /* Create an identical copy of the argument pixmap. + */ + ipixmap = XCreatePixmap( display, pixmap, width, height, depth ); + if ( 0 != ipixmap ) + { + /* Copy the argument pixmap into the new pixmap. + */ + XCopyArea( display, pixmap, ipixmap, + gc, 0, 0, width, height, 0, 0 ); + + /* Refill the new pixmap using the stipple algorithm/pixmap. + */ + XSetStipple( display, gc, stipple ); + XSetFillStyle( display, gc, FillStippled ); + XFillRectangle( display, ipixmap, gc, 0, 0, width, height ); + } + XFreeGC( display, gc ); + } + XFreePixmap( display, stipple ); + } + return ipixmap; } + diff --git a/src/motif/choice.cpp b/src/motif/choice.cpp index 9ba26a3a03..7012c75c0f 100644 --- a/src/motif/choice.cpp +++ b/src/motif/choice.cpp @@ -15,11 +15,32 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/choice.h" +#include "wx/utils.h" + +#include +#include +#include +#include + +#include "wx/motif/private.h" #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl) #endif +void wxChoiceCallback (Widget w, XtPointer clientData, + XtPointer ptr); + +wxChoice::wxChoice() +{ + m_noStrings = 0; + m_buttonWidget = (WXWidget) 0; + m_menuWidget = (WXWidget) 0; + m_widgetList = (WXWidget*) 0; + m_formWidget = (WXWidget) 0; + m_inSetValue = FALSE; +} + bool wxChoice::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, @@ -32,62 +53,320 @@ bool wxChoice::Create(wxWindow *parent, wxWindowID id, SetValidator(validator); m_noStrings = n; m_windowStyle = style; + m_buttonWidget = (WXWidget) 0; + m_menuWidget = (WXWidget) 0; + m_widgetList = (WXWidget*) 0; + m_formWidget = (WXWidget) 0; + m_inSetValue = FALSE; if (parent) parent->AddChild(this); if ( id == -1 ) m_windowId = (int)NewControlId(); else - m_windowId = id; + m_windowId = id; + + Widget parentWidget = (Widget) parent->GetClientWidget(); + + m_formWidget = (WXWidget) XtVaCreateManagedWidget ((char*) (const char*) name, + xmRowColumnWidgetClass, parentWidget, + XmNmarginHeight, 0, + XmNmarginWidth, 0, + XmNpacking, XmPACK_TIGHT, + XmNorientation, XmHORIZONTAL, + NULL); + + XtVaSetValues ((Widget) m_formWidget, XmNspacing, 0, NULL); + + /* + * Create the popup menu + */ + m_menuWidget = (WXWidget) XmCreatePulldownMenu ((Widget) m_formWidget, "choiceMenu", NULL, 0); + + int i; + if (n > 0) + { + int i; + for (i = 0; i < n; i++) + Append (choices[i]); + } + + /* + * Create button + */ + Arg args[10]; + Cardinal argcnt = 0; + + XtSetArg (args[argcnt], XmNsubMenuId, (Widget) m_menuWidget); + argcnt++; + XtSetArg (args[argcnt], XmNmarginWidth, 0); + argcnt++; + XtSetArg (args[argcnt], XmNmarginHeight, 0); + argcnt++; + XtSetArg (args[argcnt], XmNpacking, XmPACK_TIGHT); + argcnt++; + m_buttonWidget = (WXWidget) XmCreateOptionMenu ((Widget) m_formWidget, "choiceButton", args, argcnt); + + m_mainWidget = m_buttonWidget; + + XtManageChild ((Widget) m_buttonWidget); + + // New code from Roland Haenel (roland_haenel@ac.cybercity.de) + // Some time ago, I reported a problem with wxChoice-items under + // Linux and Motif 2.0 (they caused sporadic GPFs). Now it seems + // that I have found the code responsible for this behaviour. +#if XmVersion >= 1002 +#if XmVersion < 2000 + Widget optionLabel = XmOptionLabelGadget ((Widget) m_buttonWidget); + XtUnmanageChild (optionLabel); +#endif +#endif - // TODO: create choice control - return FALSE; + XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL); + + AttachWidget (parent, m_buttonWidget, m_formWidget, pos.x, pos.y, size.x, size.y); + + SetFont(* parent->GetFont()); + ChangeColour(m_mainWidget); + + return TRUE; +} + +wxChoice::~wxChoice() +{ + // For some reason destroying the menuWidget + // can cause crashes on some machines. It will + // be deleted implicitly by deleting the parent form + // anyway. +// XtDestroyWidget (menuWidget); + if (m_widgetList) + delete[] m_widgetList; + + DetachWidget(GetMainWidget()); // Removes event handlers + + XtDestroyWidget((Widget) m_formWidget); + m_formWidget = (WXWidget) 0; + + // Presumably the other widgets have been deleted now, via the form + m_mainWidget = (WXWidget) 0; + m_buttonWidget = (WXWidget) 0; } void wxChoice::Append(const wxString& item) { - // TODO - m_noStrings ++; + wxStripMenuCodes ((char *)(const char *)item, wxBuffer); + Widget w = XtVaCreateManagedWidget (wxBuffer, +#if USE_GADGETS + xmPushButtonGadgetClass, (Widget) m_menuWidget, +#else + xmPushButtonWidgetClass, (Widget) m_menuWidget, +#endif + NULL); + + if (m_windowFont.Ok()) + XtVaSetValues (w, + XmNfontList, (XmFontList) m_windowFont.GetFontList(1.0, XtDisplay((Widget) m_formWidget)), + NULL); + + WXWidget *new_widgetList = new WXWidget[m_noStrings + 1]; + int i; + for (i = 0; i < m_noStrings; i++) + new_widgetList[i] = m_widgetList[i]; + new_widgetList[m_noStrings] = (WXWidget) w; + if (m_widgetList) + delete[] m_widgetList; + m_widgetList = new_widgetList; + + char mnem = wxFindMnemonic ((char*) (const char*) item); + if (mnem != 0) + XtVaSetValues (w, XmNmnemonic, mnem, NULL); + + XtAddCallback (w, XmNactivateCallback, (XtCallbackProc) wxChoiceCallback, (XtPointer) this); + + if (m_noStrings == 0 && m_buttonWidget) + { + XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, w, NULL); + Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget); + XmString text = XmStringCreateSimple ((char*) (const char*) item); + XtVaSetValues (label, + XmNlabelString, text, + NULL); + XmStringFree (text); + } + wxNode *node = m_stringList.Add (item); + XtVaSetValues (w, XmNuserData, node->Data (), NULL); + + m_noStrings ++; } void wxChoice::Delete(int n) { + wxFAIL_MSG( "Sorry, wxChoice::Delete isn't implemented yet. Maybe you'd like to volunteer? :-)" ); + + // What should we do -- remove the callback for this button widget, + // delete the m_stringList entry, delete the button widget, construct a new widget list + // (see Append) + // TODO m_noStrings --; } void wxChoice::Clear() { - // TODO + m_stringList.Clear (); + int i; + for (i = 0; i < m_noStrings; i++) + { + XtUnmanageChild ((Widget) m_widgetList[i]); + XtDestroyWidget ((Widget) m_widgetList[i]); + } + if (m_noStrings) + delete[] m_widgetList; + m_widgetList = (WXWidget*) NULL; + if (m_buttonWidget) + XtVaSetValues ((Widget) m_buttonWidget, XmNmenuHistory, (Widget) NULL, NULL); m_noStrings = 0; } int wxChoice::GetSelection() const { - // TODO - return 0; + XmString text; + char *s; + Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget); + XtVaGetValues (label, + XmNlabelString, &text, + NULL); + + if (XmStringGetLtoR (text, XmSTRING_DEFAULT_CHARSET, &s)) + { + int i = 0; + for (wxNode * node = m_stringList.First (); node; node = node->Next ()) + { + char *s1 = (char *) node->Data (); + if (s1 == s || strcmp (s1, s) == 0) + { + XmStringFree(text) ; + XtFree (s); + return i; + } + else + i++; + } // for() + + XmStringFree(text) ; + XtFree (s); + return -1; + } + XmStringFree(text) ; + return -1; } void wxChoice::SetSelection(int n) { - // TODO + m_inSetValue = TRUE; + + wxNode *node = m_stringList.Nth (n); + if (node) + { + Dimension selectionWidth, selectionHeight; + + char *s = (char *) node->Data (); + XmString text = XmStringCreateSimple (s); + XtVaGetValues ((Widget) m_widgetList[n], XmNwidth, &selectionWidth, XmNheight, &selectionHeight, NULL); + Widget label = XmOptionButtonGadget ((Widget) m_buttonWidget); + XtVaSetValues (label, + XmNlabelString, text, + NULL); + XmStringFree (text); + XtVaSetValues ((Widget) m_buttonWidget, + XmNwidth, selectionWidth, XmNheight, selectionHeight, + XmNmenuHistory, (Widget) m_widgetList[n], NULL); + } + m_inSetValue = FALSE; } int wxChoice::FindString(const wxString& s) const { - // TODO - return 0; + int i = 0; + for (wxNode * node = m_stringList.First (); node; node = node->Next ()) + { + char *s1 = (char *) node->Data (); + if (s == s1) + { + return i; + } + else + i++; + } + return -1; } wxString wxChoice::GetString(int n) const { - // TODO - return wxString(""); + wxNode *node = m_stringList.Nth (n); + if (node) + return wxString((char *) node->Data ()); + else + return wxEmptyString; +} + +void wxChoice::SetColumns(int n) +{ + if (n<1) n = 1 ; + + short numColumns = n ; + Arg args[3]; + + XtSetArg(args[0], XmNnumColumns, numColumns); + XtSetArg(args[1], XmNpacking, XmPACK_COLUMN); + XtSetValues((Widget) m_menuWidget,args,2) ; +} + +int wxChoice::GetColumns(void) const +{ + short numColumns ; + + XtVaGetValues((Widget) m_menuWidget,XmNnumColumns,&numColumns,NULL) ; + return numColumns ; +} + +void wxChoice::SetFocus() +{ + XmProcessTraversal(XtParent((Widget)m_mainWidget), XmTRAVERSE_CURRENT); } void wxChoice::SetSize(int x, int y, int width, int height, int sizeFlags) { - // TODO + XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_ANY, NULL); + bool managed = XtIsManaged((Widget) m_formWidget); + + if (managed) + XtUnmanageChild ((Widget) m_formWidget); + + int actualWidth = width, actualHeight = height; + + if (width > -1) + { + int i; + for (i = 0; i < m_noStrings; i++) + XtVaSetValues ((Widget) m_widgetList[i], XmNwidth, actualWidth, NULL); + XtVaSetValues ((Widget) m_buttonWidget, XmNwidth, actualWidth, + NULL); + } + if (height > -1) + { + int i; + for (i = 0; i < m_noStrings; i++) + XtVaSetValues ((Widget) m_widgetList[i], XmNheight, actualHeight, NULL); + XtVaSetValues ((Widget) m_buttonWidget, XmNheight, actualHeight, + NULL); + } + + if (managed) + XtManageChild ((Widget) m_formWidget); + XtVaSetValues((Widget) m_formWidget, XmNresizePolicy, XmRESIZE_NONE, NULL); + + wxControl::SetSize (x, y, width, height, sizeFlags); } wxString wxChoice::GetStringSelection () const @@ -96,7 +375,7 @@ wxString wxChoice::GetStringSelection () const if (sel > -1) return wxString(this->GetString (sel)); else - return wxString(""); + return wxEmptyString; } bool wxChoice::SetStringSelection (const wxString& s) @@ -117,3 +396,24 @@ void wxChoice::Command(wxCommandEvent & event) ProcessCommand (event); } +void wxChoiceCallback (Widget w, XtPointer clientData, + XtPointer ptr) +{ + wxChoice *item = (wxChoice *) clientData; + if (item) + { + if (item->m_inSetValue) + return; + + char *s = NULL; + XtVaGetValues (w, XmNuserData, &s, NULL); + if (s) + { + wxCommandEvent event (wxEVT_COMMAND_CHOICE_SELECTED); + event.m_commandInt = item->FindString (s); +// event.m_commandString = s; + item->ProcessCommand (event); + } + } +} + diff --git a/src/motif/cursor.cpp b/src/motif/cursor.cpp index 4ecd0ad6d5..24c94be559 100644 --- a/src/motif/cursor.cpp +++ b/src/motif/cursor.cpp @@ -14,174 +14,418 @@ #endif #include "wx/cursor.h" +#include "wx/gdicmn.h" #include "wx/icon.h" +#include "wx/app.h" +#include "wx/utils.h" + +#include +#include + +#include "wx/motif/private.h" #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxCursor, wxBitmap) +IMPLEMENT_DYNAMIC_CLASS(wxXCursor, wxObject) #endif wxCursorRefData::wxCursorRefData() { m_width = 32; m_height = 32; - -/* TODO - m_hCursor = 0 ; -*/ + m_cursorId = wxCURSOR_NONE; } wxCursorRefData::~wxCursorRefData() { - // TODO: destroy cursor + wxNode* node = m_cursors.First(); + while (node) + { + wxXCursor* c = (wxXCursor*) node->Data(); + // TODO: how to delete cursor? + // XDestroyCursor((Display*) c->m_display, (Cursor) c->m_cursor); // ?? + delete c; + node = node->Next(); + } } -// Cursors wxCursor::wxCursor() { } -wxCursor::wxCursor(const char WXUNUSED(bits)[], int WXUNUSED(width), int WXUNUSED(height), - int WXUNUSED(hotSpotX), int WXUNUSED(hotSpotY), const char WXUNUSED(maskBits)[]) +wxCursor::wxCursor(const char bits[], int width, int height, + int hotSpotX, int hotSpotY, const char maskBits[]) { -} + m_refData = new wxCursorRefData; -wxCursor::wxCursor(const wxString& cursor_file, long flags, int hotSpotX, int hotSpotY) -{ - m_refData = new wxIconRefData; + Display *dpy = (Display*) wxGetDisplay(); + int screen_num = DefaultScreen (dpy); - // TODO: create cursor from a file -} + Pixmap pixmap = XCreatePixmapFromBitmapData (dpy, + RootWindow (dpy, DefaultScreen(dpy)), + (char*) bits, width, height, + 1 , 0 , 1); -// Cursors by stock number -wxCursor::wxCursor(int cursor_type) -{ - m_refData = new wxIconRefData; - -/* TODO - switch (cursor_type) - { - case wxCURSOR_WAIT: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_WAIT); - break; - case wxCURSOR_IBEAM: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_IBEAM); - break; - case wxCURSOR_CROSS: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_CROSS); - break; - case wxCURSOR_SIZENWSE: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZENWSE); - break; - case wxCURSOR_SIZENESW: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZENESW); - break; - case wxCURSOR_SIZEWE: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZEWE); - break; - case wxCURSOR_SIZENS: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_SIZENS); - break; - case wxCURSOR_CHAR: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW); - break; - } - case wxCURSOR_HAND: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_HAND"); - break; - } - case wxCURSOR_BULLSEYE: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_BULLSEYE"); - break; - } - case wxCURSOR_PENCIL: + Pixmap mask_pixmap = None; + if (maskBits != NULL) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PENCIL"); - break; + mask_pixmap = XCreatePixmapFromBitmapData (dpy, + RootWindow (dpy, DefaultScreen(dpy)), + (char*) maskBits, width, height, + 1 , 0 , 1); } - case wxCURSOR_MAGNIFIER: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_MAGNIFIER"); - break; - } - case wxCURSOR_NO_ENTRY: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_NO_ENTRY"); - break; - } - case wxCURSOR_LEFT_BUTTON: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW); - break; - } - case wxCURSOR_RIGHT_BUTTON: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW); - break; - } - case wxCURSOR_MIDDLE_BUTTON: - { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW); - break; - } - case wxCURSOR_SIZING: + + XColor foreground_color; + XColor background_color; + foreground_color.pixel = BlackPixel(dpy, screen_num); + background_color.pixel = WhitePixel(dpy, screen_num); + Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy); + XQueryColor(dpy, cmap, &foreground_color); + XQueryColor(dpy, cmap, &background_color); + + Cursor cursor = XCreatePixmapCursor (dpy, + pixmap, + mask_pixmap, + &foreground_color, + &background_color, + hotSpotX , + hotSpotY); + + XFreePixmap( dpy, pixmap ); + if (mask_pixmap != None) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_SIZING"); - break; + XFreePixmap( dpy, mask_pixmap ); } - case wxCURSOR_WATCH: + + if (cursor) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_WATCH"); - break; + wxXCursor *c = new wxXCursor; + + c->m_cursor = (WXCursor) cursor; + c->m_display = (WXDisplay*) dpy; + M_CURSORDATA->m_cursors.Append(c); + M_CURSORDATA->m_ok = TRUE; } - case wxCURSOR_SPRAYCAN: + else { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_ROLLER"); - break; + M_CURSORDATA->m_ok = TRUE; } - case wxCURSOR_PAINT_BRUSH: +} + +wxCursor::wxCursor(const wxString& name, long flags, int hotSpotX, int hotSpotY) +{ + // Must be an XBM file + if (flags != wxBITMAP_TYPE_XBM) + return; + + m_refData = new wxCursorRefData; + + int hotX = -1, hotY = -1; + unsigned int w, h; + Pixmap pixmap; + + Display *dpy = (Display*) wxGetDisplay(); + int screen_num = DefaultScreen (dpy); + + int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)), + (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY); + + M_BITMAPDATA->m_width = w; + M_BITMAPDATA->m_height = h; + M_BITMAPDATA->m_depth = 1; + + if ((value == BitmapFileInvalid) || + (value == BitmapOpenFailed) || + (value == BitmapNoMemory)) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PBRUSH"); - break; } - case wxCURSOR_POINT_LEFT: + else { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PLEFT"); - break; + XColor foreground_color; + XColor background_color; + foreground_color.pixel = BlackPixel(dpy, screen_num); + background_color.pixel = WhitePixel(dpy, screen_num); + Colormap cmap = (Colormap) wxTheApp->GetMainColormap((WXDisplay*) dpy); + XQueryColor(dpy, cmap, &foreground_color); + XQueryColor(dpy, cmap, &background_color); + + // TODO: how do we determine whether hotX, hotY were read correctly? + if (hotX < 0 || hotY < 0) + { + hotX = hotSpotX; + hotY = hotSpotY; + } + if (hotX < 0 || hotY < 0) + { + hotX = 0; + hotY = 0; + } + + Pixmap mask_pixmap = None; + Cursor cursor = XCreatePixmapCursor (dpy, + pixmap, + mask_pixmap, + &foreground_color, + &background_color, + hotX, + hotY); + + XFreePixmap( dpy, pixmap ); + if (cursor) + { + wxXCursor *c = new wxXCursor; + + c->m_cursor = (WXCursor) cursor; + c->m_display = (WXDisplay*) dpy; + M_CURSORDATA->m_cursors.Append(c); + M_CURSORDATA->m_ok = TRUE; + } } - case wxCURSOR_POINT_RIGHT: + +} + +// Cursors by stock number +wxCursor::wxCursor(wxStockCursor id) +{ + m_refData = new wxCursorRefData; + M_CURSORDATA->m_cursorId = id; + + WXCursor cursor = GetXCursor(wxGetDisplay()); + if (cursor) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_PRIGHT"); - break; + wxXCursor* c = new wxXCursor; + c->m_cursor = cursor; + c->m_display = wxGetDisplay(); + M_CURSORDATA->m_cursors.Append(c); + M_CURSORDATA->m_ok = TRUE; } - case wxCURSOR_QUESTION_ARROW: +} + +wxCursor::~wxCursor() +{ +} + +// Motif-specific: create/get a cursor for the current display +WXCursor wxCursor::GetXCursor(WXDisplay* display) +{ + if (!M_CURSORDATA) + return (WXCursor) 0; + wxNode* node = M_CURSORDATA->m_cursors.First(); + while (node) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_QARROW"); - break; + wxXCursor* c = (wxXCursor*) node->Data(); + if (c->m_display == display) + return c->m_cursor; + node = node->Next(); } - case wxCURSOR_BLANK: + + // No cursor for this display, so let's see if we're an id-type cursor. + + if (M_CURSORDATA->m_cursorId != wxCURSOR_NONE) { - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(wxGetInstance(), "wxCURSOR_BLANK"); - break; + WXCursor cursor = MakeCursor(display, M_CURSORDATA->m_cursorId); + if (cursor) + { + wxXCursor* c = new wxXCursor; + c->m_cursor = cursor; + c->m_display = display; + M_CURSORDATA->m_cursors.Append(c); + return cursor; + } + else + return (WXCursor) 0; } - default: - case wxCURSOR_ARROW: - M_CURSORDATA->m_hCursor = (WXHCURSOR) LoadCursor(NULL, IDC_ARROW); - break; - } -*/ + // Not an id-type cursor, so we don't know how to create it. + return (WXCursor) 0; } -wxCursor::~wxCursor() +// Make a cursor from standard id +WXCursor wxCursor::MakeCursor(WXDisplay* display, wxStockCursor id) { + Display* dpy = (Display*) display; + Cursor cursor = (Cursor) 0; + + switch (id) + { + case wxCURSOR_WAIT: + { + cursor = XCreateFontCursor (dpy, XC_watch); + break; + } + case wxCURSOR_CROSS: + { + cursor = XCreateFontCursor (dpy, XC_crosshair); + break; + } + case wxCURSOR_CHAR: + { + // Nothing + break; + } + case wxCURSOR_HAND: + { + cursor = XCreateFontCursor (dpy, XC_hand1); + break; + } + case wxCURSOR_BULLSEYE: + { + cursor = XCreateFontCursor (dpy, XC_target); + break; + } + case wxCURSOR_PENCIL: + { + cursor = XCreateFontCursor (dpy, XC_pencil); + break; + } + case wxCURSOR_MAGNIFIER: + { + cursor = XCreateFontCursor (dpy, XC_sizing); + break; + } + case wxCURSOR_IBEAM: + { + cursor = XCreateFontCursor (dpy, XC_xterm); + break; + } + case wxCURSOR_NO_ENTRY: + { + cursor = XCreateFontCursor (dpy, XC_pirate); + break; + } + case wxCURSOR_LEFT_BUTTON: + { + cursor = XCreateFontCursor (dpy, XC_leftbutton); + break; + } + case wxCURSOR_RIGHT_BUTTON: + { + cursor = XCreateFontCursor (dpy, XC_rightbutton); + break; + } + case wxCURSOR_MIDDLE_BUTTON: + { + cursor = XCreateFontCursor (dpy, XC_middlebutton); + break; + } + case wxCURSOR_QUESTION_ARROW: + { + cursor = XCreateFontCursor (dpy, XC_question_arrow); + break; + } + case wxCURSOR_SIZING: + { + cursor = XCreateFontCursor (dpy, XC_sizing); + break; + } + case wxCURSOR_WATCH: + { + cursor = XCreateFontCursor (dpy, XC_watch); + break; + } + case wxCURSOR_SPRAYCAN: + { + cursor = XCreateFontCursor (dpy, XC_spraycan); + break; + } + case wxCURSOR_PAINT_BRUSH: + { + cursor = XCreateFontCursor (dpy, XC_spraycan); + break; + } + case wxCURSOR_SIZENWSE: + case wxCURSOR_SIZENESW: + { + // Not available in X + cursor = XCreateFontCursor (dpy, XC_crosshair); + break; + } + case wxCURSOR_SIZEWE: + { + cursor = XCreateFontCursor (dpy, XC_sb_h_double_arrow); + break; + } + case wxCURSOR_SIZENS: + { + cursor = XCreateFontCursor (dpy, XC_sb_v_double_arrow); + break; + } + case wxCURSOR_POINT_LEFT: + { + cursor = XCreateFontCursor (dpy, XC_sb_left_arrow); + break; + } + case wxCURSOR_POINT_RIGHT: + { + cursor = XCreateFontCursor (dpy, XC_sb_right_arrow); + break; + } + // (JD Huggins) added more stock cursors for X + // X-only cursors BEGIN + case wxCURSOR_CROSS_REVERSE: + { + cursor = XCreateFontCursor(dpy, XC_cross_reverse); + break; + } + case wxCURSOR_DOUBLE_ARROW: + { + cursor = XCreateFontCursor(dpy, XC_double_arrow); + break; + } + case wxCURSOR_BASED_ARROW_UP: + { + cursor = XCreateFontCursor(dpy, XC_based_arrow_up); + break; + } + case wxCURSOR_BASED_ARROW_DOWN: + { + cursor = XCreateFontCursor(dpy, XC_based_arrow_down); + break; + } + default: + case wxCURSOR_ARROW: + { + cursor = XCreateFontCursor (dpy, XC_top_left_arrow); + break; + } + case wxCURSOR_BLANK: + { + GC gc; + XGCValues gcv; + Pixmap empty_pixmap; + XColor blank_color; + + empty_pixmap = XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)), + 16, 16, 1); + gcv.function = GXxor; + gc = XCreateGC (dpy, + empty_pixmap, + GCFunction, + &gcv); + XCopyArea (dpy, + empty_pixmap, + empty_pixmap, + gc, + 0, 0, + 16, 16, + 0, 0); + XFreeGC (dpy, gc); + cursor = XCreatePixmapCursor (dpy, + empty_pixmap, + empty_pixmap, + &blank_color, + &blank_color, + 8, 8); + + break; + } + } + return (WXCursor) cursor; } // Global cursor setting void wxSetCursor(const wxCursor& cursor) { - // TODO (optional on platforms with no global cursor) + // Nothing to do for Motif (no global cursor) } diff --git a/src/motif/dcclient.cpp b/src/motif/dcclient.cpp index 9f994b2747..ebe87a10d5 100644 --- a/src/motif/dcclient.cpp +++ b/src/motif/dcclient.cpp @@ -1081,7 +1081,7 @@ void wxWindowDC::DrawText( const wxString &text, long x, long y, bool use16 ) if (m_font.Ok()) { - WXFontStructPtr pFontStruct = m_font.FindOrCreateFontStruct(m_userScaleY*m_logicalScaleY); + WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); int direction, descent; XCharStruct overall_return; if (use16) @@ -1235,7 +1235,7 @@ void wxWindowDC::GetTextExtent( const wxString &string, long *width, long *heigh return; } - WXFontStructPtr pFontStruct = theFont->FindOrCreateFontStruct(m_userScaleY*m_logicalScaleY); + WXFontStructPtr pFontStruct = theFont->GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); int direction, ascent, descent2; XCharStruct overall; @@ -1265,7 +1265,7 @@ long wxWindowDC::GetCharWidth(void) if (!m_font.Ok()) return 0; - WXFontStructPtr pFontStruct = m_font.FindOrCreateFontStruct(m_userScaleY * m_logicalScaleY); + WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY * m_logicalScaleY, m_display); int direction, ascent, descent; XCharStruct overall; @@ -1281,7 +1281,7 @@ long wxWindowDC::GetCharHeight(void) if (!m_font.Ok()) return 0; - WXFontStructPtr pFontStruct = m_font.FindOrCreateFontStruct(m_userScaleY*m_logicalScaleY); + WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); int direction, ascent, descent; XCharStruct overall; @@ -1348,7 +1348,7 @@ void wxWindowDC::SetFont( const wxFont &font ) return; } - WXFontStructPtr pFontStruct = m_font.FindOrCreateFontStruct(m_userScaleY*m_logicalScaleY); + WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display); Font fontId = ((XFontStruct*)pFontStruct)->fid; XSetFont ((Display*) m_display, (GC) m_gc, fontId); diff --git a/src/motif/filedlg.cpp b/src/motif/filedlg.cpp index fdd54ea7b2..04966afc99 100644 --- a/src/motif/filedlg.cpp +++ b/src/motif/filedlg.cpp @@ -19,6 +19,8 @@ #include "wx/filedlg.h" #include "wx/intl.h" +#include + #if !USE_SHARED_LIBRARY IMPLEMENT_CLASS(wxFileDialog, wxDialog) #endif @@ -84,6 +86,176 @@ char *wxFileSelectorEx(const char *title, return NULL; } +// TODO: Motif file selector code +#if 0 +char *wxFileSelectorAnswer = NULL; +Bool wxFileSelectorReturned = FALSE; + +void wxFileSelCancel(Widget fs, XtPointer client_data, XmFileSelectionBoxCallbackStruct *cbs) +{ + wxFileSelectorAnswer = NULL; + wxFileSelectorReturned = TRUE; +} + +void wxFileSelOk(Widget fs, XtPointer client_data, XmFileSelectionBoxCallbackStruct *cbs) +{ + char *filename = NULL; + if (!XmStringGetLtoR(cbs->value, XmSTRING_DEFAULT_CHARSET, &filename)) { + wxFileSelectorAnswer = NULL; + wxFileSelectorReturned = TRUE; + } else { + if (filename) { + if (wxFileSelectorAnswer) delete[] wxFileSelectorAnswer; + wxFileSelectorAnswer = copystring(filename); + XtFree(filename); + } + wxFileSelectorReturned = TRUE; + } +} + + +char *wxMotifFileSelector(char *message, + char *default_path, char *default_filename, + char *default_extension, char *wildcard, int flags, + wxWindow *parent, int x, int y) +{ + wxBeginBusyCursor(); + static char fileBuf[512]; + Widget parentWidget = 0; + if (parent) + { + if (parent->IsKindOf(CLASSINFO(wxFrame))) + parentWidget = ((wxFrame *)parent)->frameShell; + else if (parent->IsKindOf(CLASSINFO(wxDialogBox))) + parentWidget = ((wxDialogBox *)parent)->dialogShell; + else + parentWidget = (Widget)parent->handle; + } + else if (wxTheApp->wx_frame) + parentWidget = wxTheApp->wx_frame->frameShell; + + Widget fileSel = XmCreateFileSelectionDialog(parentWidget, "file_selector", NULL, 0); + XtUnmanageChild(XmFileSelectionBoxGetChild(fileSel, XmDIALOG_HELP_BUTTON)); + + Widget shell = XtParent(fileSel); + + if (message) + XtVaSetValues(shell, XmNtitle, message, NULL); + + char *entirePath = NULL; + + if (default_path && default_filename) + { + sprintf(wxBuffer, "%s/%s", default_path, default_filename); + entirePath = copystring(wxBuffer); + } + else if (default_path && !default_filename) + { + sprintf(wxBuffer, "%s/", default_path); + entirePath = copystring(wxBuffer); + } + else if ((!default_path) && default_filename) + { + sprintf(wxBuffer, "%s", default_filename); + entirePath = copystring(wxBuffer); + } + + if (entirePath) + { + Widget selectionWidget = XmFileSelectionBoxGetChild(fileSel, XmDIALOG_TEXT); + XmTextSetString(selectionWidget, entirePath); + delete[] entirePath; + } + + if (wildcard) + { + if (default_path) + sprintf(wxBuffer, "%s/%s", default_path, wildcard); + else + sprintf(wxBuffer, "%s", wildcard); + + Widget filterWidget = XmFileSelectionBoxGetChild(fileSel, XmDIALOG_FILTER_TEXT); + XmTextSetString(filterWidget, wxBuffer); + XmFileSelectionDoSearch(fileSel, NULL); + } + + // Suggested by Terry Gitnick, 16/9/97, because of change in Motif + // file selector on Solaris 1.5.1. + if ( default_path ) + { + XmString thePath = XmStringCreateLtoR (default_path, + XmSTRING_DEFAULT_CHARSET); + + XtVaSetValues (fileSel, + XmNdirectory, thePath, + NULL); + + XmStringFree(thePath); + } + + XtAddCallback(fileSel, XmNcancelCallback, (XtCallbackProc)wxFileSelCancel, (XtPointer)NULL); + XtAddCallback(fileSel, XmNokCallback, (XtCallbackProc)wxFileSelOk, (XtPointer)NULL); + +//#if XmVersion > 1000 +// I'm not sure about what you mean with XmVersion. +// If this is for Motif1.1/Motif1.2, then check XmVersion>=1200 +// (Motif1.1.4 ==> XmVersion 1100 ) +// Nevertheless, I put here a #define, so anyone can choose in (I)makefile... +// +#if !DEFAULT_FILE_SELECTOR_SIZE + int width = wxFSB_WIDTH; + int height = wxFSB_HEIGHT; + XtVaSetValues(fileSel, + XmNwidth, width, + XmNheight, height, + XmNresizePolicy, XmRESIZE_NONE, + NULL); +#endif + + XtManageChild(fileSel); + + if (wxFileSelectorAnswer) + delete[] wxFileSelectorAnswer; + + wxFileSelectorAnswer = NULL; + wxFileSelectorReturned = FALSE; + + wxEndBusyCursor(); + + XtAddGrab(XtParent(fileSel), TRUE, FALSE); + XEvent event; + while (!wxFileSelectorReturned) + { + XtAppNextEvent(wxTheApp->appContext, &event); + XtDispatchEvent(&event); + } + XtRemoveGrab(XtParent(fileSel)); + + XmUpdateDisplay(wxTheApp->topLevel); // Experimental + +// XtDestroyWidget(fileSel); + XtUnmapWidget(XtParent(fileSel)); + XtDestroyWidget(XtParent(fileSel)); + + // Now process all events, because otherwise + // this might remain on the screen + XSync(XtDisplay(wxTheApp->topLevel), FALSE); + while (XtAppPending(wxTheApp->appContext)) + { + XFlush(XtDisplay(wxTheApp->topLevel)); + XtAppNextEvent(wxTheApp->appContext, &event); + XtDispatchEvent(&event); + } + + if (wxFileSelectorAnswer) + { + strcpy(fileBuf, wxFileSelectorAnswer); + return fileBuf; + } + else return NULL; +} +#endif + wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message, const wxString& defaultDir, const wxString& defaultFileName, const wxString& wildCard, long style, const wxPoint& pos) diff --git a/src/motif/font.cpp b/src/motif/font.cpp index ae4ccd07ff..c03570a342 100644 --- a/src/motif/font.cpp +++ b/src/motif/font.cpp @@ -19,13 +19,33 @@ #include "wx/gdicmn.h" #include "wx/utils.h" -#include +#include #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject) #endif -wxFontRefData::wxFontRefData(): m_fontsByScale(wxKEY_INTEGER) +wxXFont::wxXFont() +{ + m_fontStruct = (WXFontStructPtr) 0; + m_fontList = (WXFontList) 0; + m_display = (WXDisplay*) 0; + m_scale = 100; +} + +wxXFont::~wxXFont() +{ + XFontStruct* fontStruct = (XFontStruct*) m_fontStruct; + XmFontList fontList = (XmFontList) m_fontList; + + XmFontListFree (fontList); + + // TODO: why does freeing the font produce a segv??? + // Note that XFreeFont wasn't called in wxWin 1.68 either. + // XFreeFont((Display*) m_display, fontStruct); +} + +wxFontRefData::wxFontRefData() { m_style = 0; m_pointSize = 0; @@ -36,7 +56,7 @@ wxFontRefData::wxFontRefData(): m_fontsByScale(wxKEY_INTEGER) m_faceName = ""; } -wxFontRefData::wxFontRefData(const wxFontRefData& data): m_fontsByScale(wxKEY_INTEGER) +wxFontRefData::wxFontRefData(const wxFontRefData& data) { m_style = data.m_style; m_pointSize = data.m_pointSize; @@ -52,17 +72,14 @@ wxFontRefData::wxFontRefData(const wxFontRefData& data): m_fontsByScale(wxKEY_IN wxFontRefData::~wxFontRefData() { - wxNode* node = m_fontsByScale.First(); + wxNode* node = m_fonts.First(); while (node) { - XFontStruct* fontStruct = (XFontStruct*) node->Data(); - // TODO: why does freeing the font produce a segv??? - // Commenting it out will result in memory leaks, and - // maybe X resource problems, who knows... - // XFreeFont((Display*) wxGetDisplay, fontStruct); + wxXFont* f = (wxXFont*) node->Data(); + delete f; node = node->Next(); } - m_fontsByScale.Clear(); + m_fonts.Clear(); } wxFont::wxFont() @@ -255,18 +272,21 @@ wxString wxFont::GetWeightString() const // Find an existing, or create a new, XFontStruct // based on this wxFont and the given scale. Append the // font to list in the private data for future reference. -WXFontStructPtr wxFont::FindOrCreateFontStruct(double scale) +wxXFont* wxFont::GetInternalFont(double scale, WXDisplay* display) const { if (!Ok()) - return NULL; + return (wxXFont*) NULL; - long intScale = long(scale * 100.0 + 0.5); // key for fontlist + long intScale = long(scale * 100.0 + 0.5); // key for wxXFont int pointSize = (M_FONTDATA->m_pointSize * 10 * intScale) / 100; - wxNode* node = M_FONTDATA->m_fontsByScale.Find(intScale); - if (node) + wxNode* node = M_FONTDATA->m_fonts.First(); + while (node) { - return (WXFontStructPtr) node->Data(); + wxXFont* f = (wxXFont*) node->Data(); + if ((!display || (f->m_display == display)) && (f->m_scale == intScale)) + return f; + node = node->Next(); } WXFontStructPtr font = LoadQueryFont(pointSize, M_FONTDATA->m_family, @@ -297,14 +317,19 @@ WXFontStructPtr wxFont::FindOrCreateFontStruct(double scale) } if (font) { - M_FONTDATA->m_fontsByScale.Append(intScale, (wxObject*) font); - return (WXFontStructPtr) font; + wxXFont* f = new wxXFont; + f->m_fontStruct = font; + f->m_display = ( display ? display : wxGetDisplay() ); + f->m_scale = intScale; + f->m_fontList = XmFontListCreate ((XFontStruct*) font, XmSTRING_DEFAULT_CHARSET); + M_FONTDATA->m_fonts.Append(f); + return f; } - return font; + return (wxXFont*) NULL; } WXFontStructPtr wxFont::LoadQueryFont(int pointSize, int family, int style, - int weight, bool underlined) + int weight, bool underlined) const { char *xfamily; char *xstyle; diff --git a/src/motif/icon.cpp b/src/motif/icon.cpp index 834c9ff1cc..0f3ff04a64 100644 --- a/src/motif/icon.cpp +++ b/src/motif/icon.cpp @@ -14,6 +14,12 @@ #endif #include "wx/icon.h" +#include "wx/window.h" + +#include +#include + +#include "wx/motif/private.h" #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxIcon, wxBitmap) @@ -23,23 +29,20 @@ IMPLEMENT_DYNAMIC_CLASS(wxIcon, wxBitmap) * Icons */ - -wxIconRefData::wxIconRefData() -{ - // TODO: init icon handle -} - -wxIconRefData::~wxIconRefData() +wxIcon::wxIcon() { - // TODO: destroy icon handle } -wxIcon::wxIcon() +// Create from XBM data +wxIcon::wxIcon(const char bits[], int width, int height) { + (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, 1); } -wxIcon::wxIcon(const char WXUNUSED(bits)[], int WXUNUSED(width), int WXUNUSED(height)) +// Create from XPM data +wxIcon::wxIcon(const char **data) { + (void) Create((void*) data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0); } wxIcon::wxIcon(const wxString& icon_file, long flags, @@ -58,7 +61,7 @@ bool wxIcon::LoadFile(const wxString& filename, long type, { UnRef(); - m_refData = new wxIconRefData; + m_refData = new wxBitmapRefData; wxBitmapHandler *handler = FindHandler(type); diff --git a/src/motif/listbox.cpp b/src/motif/listbox.cpp index 9352c32bc2..2dffe82cb1 100644 --- a/src/motif/listbox.cpp +++ b/src/motif/listbox.cpp @@ -17,20 +17,30 @@ #include "wx/settings.h" #include "wx/dynarray.h" #include "wx/log.h" +#include "wx/utils.h" + +#include +#include "wx/motif/private.h" #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) #endif +void wxListBoxCallback (Widget w, XtPointer clientData, + XmListCallbackStruct * cbs); + +void wxListBoxDefaultActionProc (Widget list_w, XtPointer client_data, XmListCallbackStruct * cbs); + // ============================================================================ // list box control implementation // ============================================================================ // Listbox item -wxListBox::wxListBox() +wxListBox::wxListBox(): m_clientDataList(wxKEY_INTEGER) { - m_noItems = 0; - m_selected = 0; + m_noItems = 0; + m_selected = 0; + m_inSetValue = FALSE; } bool wxListBox::Create(wxWindow *parent, wxWindowID id, @@ -41,22 +51,69 @@ bool wxListBox::Create(wxWindow *parent, wxWindowID id, const wxValidator& validator, const wxString& name) { - m_noItems = n; - m_selected = 0; + m_inSetValue = FALSE; + m_windowStyle = style; + m_noItems = n; + m_selected = 0; + + SetName(name); + SetValidator(validator); + + if (parent) parent->AddChild(this); + + m_windowId = ( id == -1 ) ? (int)NewControlId() : id; + + Widget parentWidget = (Widget) parent->GetClientWidget(); + + Arg args[3]; + int count; + XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); + if (m_windowStyle & wxLB_MULTIPLE) + XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); + else if (m_windowStyle & wxLB_EXTENDED) + XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); + else + XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); + if (m_windowStyle & wxLB_ALWAYS_SB) + { + XtSetArg (args[2], XmNscrollBarDisplayPolicy, XmSTATIC); + count = 3; + } + else + count = 2; - SetName(name); - SetValidator(validator); + Widget listWidget = XmCreateScrolledList (parentWidget, (char*) (const char*) name, args, count); - if (parent) parent->AddChild(this); + m_mainWidget = (WXWidget) listWidget; - wxSystemSettings settings; - SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + XtManageChild (listWidget); - m_windowId = ( id == -1 ) ? (int)NewControlId() : id; + long width = size.x; + long height = size.y; + if (width == -1) + width = 150; + if (height == -1) + height = 80; - // TODO create listbox + XtAddCallback (listWidget, XmNbrowseSelectionCallback, (XtCallbackProc) wxListBoxCallback, + (XtPointer) this); + XtAddCallback (listWidget, XmNextendedSelectionCallback, (XtCallbackProc) wxListBoxCallback, + (XtPointer) this); + XtAddCallback (listWidget, XmNmultipleSelectionCallback, (XtCallbackProc) wxListBoxCallback, + (XtPointer) this); - return FALSE; + XtAddCallback (listWidget, XmNdefaultActionCallback, (XtCallbackProc) wxListBoxDefaultActionProc, + (XtPointer) this); + + AttachWidget (parent, m_mainWidget, (WXWidget) NULL, pos.x, pos.y, width, height); + + wxSystemSettings settings; + SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); + + SetFont(* parent->GetFont()); + ChangeColour(m_mainWidget); + + return TRUE; } wxListBox::~wxListBox() @@ -65,171 +122,608 @@ wxListBox::~wxListBox() void wxListBox::SetFirstItem(int N) { - // TODO + int count, length; + + if (N < 0) + return; + XtVaGetValues ((Widget) m_mainWidget, + XmNvisibleItemCount, &count, + XmNitemCount, &length, + NULL); + if ((N + count) >= length) + N = length - count; + XmListSetPos ((Widget) m_mainWidget, N + 1); } void wxListBox::SetFirstItem(const wxString& s) { - // TODO + int N = FindString (s); + + if (N >= 0) + SetFirstItem (N); } void wxListBox::Delete(int N) { + int width1, height1; + int width2, height2; + Widget listBox = (Widget) m_mainWidget; + GetSize (&width1, &height1); + + bool managed = XtIsManaged(listBox); + + if (managed) + XtUnmanageChild (listBox); + + XmListDeletePos (listBox, N + 1); + + if (managed) + XtManageChild (listBox); + + GetSize (&width2, &height2); + // Correct for randomly resized listbox - bad boy, Motif! + if (width1 != width2 || height1 != height2) + SetSize (-1, -1, width1, height1); + + // (JDH) need to add code here to take care of clientDataList + wxNode *node = m_clientDataList.Find((long)N); // get item from list + if (node) m_clientDataList.DeleteNode(node); // if existed then delete from list + node = m_clientDataList.First(); // we now have to adjust all keys that + while (node) // are >=N+1 + { if (node->key.integer >= (long)(N+1)) // very ugly C++ wise but no other way + node->key.integer--; // to look at or change key value + node = node->Next(); + } + m_noItems --; - // TODO } void wxListBox::Append(const wxString& item) { - m_noItems ++; + int width1, height1; + int width2, height2; + + Widget listBox = (Widget) m_mainWidget; + GetSize (&width1, &height1); + + bool managed = XtIsManaged(listBox); + + if (managed) + XtUnmanageChild (listBox); + int n; + XtVaGetValues (listBox, XmNitemCount, &n, NULL); + XmString text = XmStringCreateSimple ((char*) (const char*) item); +// XmListAddItem(listBox, text, n + 1); + XmListAddItemUnselected (listBox, text, 0); + XmStringFree (text); + + // It seems that if the list is cleared, we must re-ask for + // selection policy!! + Arg args[3]; + XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); + if (m_windowStyle & wxLB_MULTIPLE) + XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); + else if (m_windowStyle & wxLB_EXTENDED) + XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); + else + XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); + XtSetValues (listBox, args, 2); + + if (managed) + XtManageChild (listBox); - // TODO + GetSize (&width2, &height2); + // Correct for randomly resized listbox - bad boy, Motif! + if (width1 != width2 || height1 != height2) + SetSize (-1, -1, width1, height1); + m_noItems ++; } -void wxListBox::Append(const wxString& item, char *Client_data) +void wxListBox::Append(const wxString& item, char *clientData) { - m_noItems ++; + int width1, height1; + int width2, height2; + + Widget listBox = (Widget) m_mainWidget; + + GetSize (&width1, &height1); + Bool managed = XtIsManaged(listBox); + + if (managed) + XtUnmanageChild (listBox); + + int n; + XtVaGetValues (listBox, XmNitemCount, &n, NULL); + XmString text = XmStringCreateSimple ((char*) (const char*) item); +// XmListAddItem(listBox, text, n + 1); + XmListAddItemUnselected (listBox, text, 0); + XmStringFree (text); + + // It seems that if the list is cleared, we must re-ask for + // selection policy!! + Arg args[3]; + XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); + if (m_windowStyle & wxLB_MULTIPLE) + XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); + else if (m_windowStyle & wxLB_EXTENDED) + XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); + else + XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); + XtSetValues (listBox, args, 2); + + m_clientDataList.Append ((long) n, (wxObject *) clientData); + + if (managed) + XtManageChild (listBox); + + GetSize (&width2, &height2); + + // Correct for randomly resized listbox - bad boy, Motif! + if (width1 != width2 || height1 != height2) + SetSize (-1, -1, width1, height1); - // TODO + m_noItems ++; } void wxListBox::Set(int n, const wxString *choices, char** clientData) { - m_noItems = n; + m_clientDataList.Clear(); + int width1, height1; + int width2, height2; + + Widget listBox = (Widget) m_mainWidget; + GetSize (&width1, &height1); + + bool managed = XtIsManaged(listBox); + + if (managed) + XtUnmanageChild (listBox); +/*** + for (int i=0; iData (); + else + return NULL; } void wxListBox::SetClientData(int N, char *Client_data) { - // TODO + wxNode *node = m_clientDataList.Find ((long) N); + if (node) + node->SetData ((wxObject *)Client_data); } // Return number of selections and an array of selected integers int wxListBox::GetSelections(wxArrayInt& aSelections) const { - aSelections.Empty(); - -/* TODO - if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED)) - { - int no_sel = ?? - for ( int n = 0; n < no_sel; n++ ) - aSelections.Add(??); - - return no_sel; - } - else // single-selection listbox - { - aSelections.Add(??); - - return 1; + aSelections.Empty(); + + Widget listBox = (Widget) m_mainWidget; + int *posList = NULL; + int posCnt = 0; + bool flag = XmListGetSelectedPos (listBox, &posList, &posCnt); + if (flag) + { + if (posCnt > 0) + { + aSelections.Alloc(posCnt); + + int i; + for (i = 0; i < posCnt; i++) + aSelections.Add(posList[i] - 1); + + XtFree ((char *) posList); + return posCnt; + } + else + return 0; } -*/ + else return 0; } // Get single selection, for single choice list items int wxListBox::GetSelection() const { - // TODO - return -1; + Widget listBox = (Widget) m_mainWidget; + int *posList = NULL; + int posCnt = 0; + bool flag = XmListGetSelectedPos (listBox, &posList, &posCnt); + if (flag) + { + int id = -1; + if (posCnt > 0) + id = posList[0] - 1; + XtFree ((char *) posList); + return id; + } + else + return -1; } // Find string for position wxString wxListBox::GetString(int N) const { - // TODO - return wxString(""); + Widget listBox = (Widget) m_mainWidget; + XmString *strlist; + int n; + XtVaGetValues (listBox, XmNitemCount, &n, XmNitems, &strlist, NULL); + if (N <= n && N >= 0) + { + char *txt; + if (XmStringGetLtoR (strlist[N], XmSTRING_DEFAULT_CHARSET, &txt)) + { + wxString str(txt); + XtFree (txt); + return str; + } + else + return wxEmptyString; + } + else + return wxEmptyString; } void wxListBox::SetSize(int x, int y, int width, int height, int sizeFlags) { - // TODO + wxWindow::SetSize(x, y, width, height, sizeFlags); + + // Check resulting size is correct + int tempW, tempH; + GetSize (&tempW, &tempH); } void wxListBox::InsertItems(int nItems, const wxString items[], int pos) { - m_noItems += nItems; + int width1, height1; + int width2, height2; + + Widget listBox = (Widget) m_mainWidget; + + GetSize(&width1, &height1); + + bool managed = XtIsManaged(listBox); + + if (managed) + XtUnmanageChild(listBox); + + XmString *text = new XmString[nItems]; + int i; + // Steve Hammes: Motif 1.1 compatibility +// #if XmVersion > 1100 +// Corrected by Sergey Krasnov from Steve Hammes' code +#if XmVersion > 1001 + for (i = 0; i < nItems; i++) + text[i] = XmStringCreateSimple((char*) (const char*) items[i]); + XmListAddItemsUnselected(listBox, text, nItems, pos+1); +#else + for (i = 0; i < nItems; i++) + { + text[i] = XmStringCreateSimple((char*) (const char*) items[i]); +// XmListAddItemUnselected(listBox, text[i], i); + XmListAddItemUnselected(listBox, text[i], pos+i+1); // Another Sergey correction + } +#endif + for (i = 0; i < nItems; i++) + XmStringFree(text[i]); + + delete[] text; + + // It seems that if the list is cleared, we must re-ask for + // selection policy!! + Arg args[3]; + XtSetArg(args[0], XmNlistSizePolicy, XmCONSTANT); + if (m_windowStyle & wxLB_MULTIPLE) + XtSetArg(args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); + else if (m_windowStyle & wxLB_EXTENDED) + XtSetArg(args[1], XmNselectionPolicy, XmEXTENDED_SELECT); + else XtSetArg(args[1], XmNselectionPolicy, XmBROWSE_SELECT); + XtSetValues(listBox,args,2) ; + + if (managed) + XtManageChild(listBox); + + GetSize(&width2, &height2); + // Correct for randomly resized listbox - bad boy, Motif! + if (width1 != width2 /*|| height1 != height2*/) + SetSize(-1, -1, width1, height1); - // TODO + m_noItems += nItems; } void wxListBox::SetString(int N, const wxString& s) { - // TODO + int width1, height1; + int width2, height2; + + Widget listBox = (Widget) m_mainWidget; + GetSize (&width1, &height1); + + XmString text = XmStringCreateSimple ((char*) (const char*) s); + + // WHAT'S THE MOTIF CALL TO SET THE TEXT OF AN EXISTING + // ITEM??? + // There isn't one, so delete the item and add it again. + XmListDeletePos (listBox, N+1); + XmListAddItem (listBox, text, N+1); + + XmStringFree(text); + +/* + // It seems that if the list is cleared, we must re-ask for + // selection policy!! + Arg args[3]; + XtSetArg (args[0], XmNlistSizePolicy, XmCONSTANT); + if (m_windowStyle & wxLB_MULTIPLE) + XtSetArg (args[1], XmNselectionPolicy, XmMULTIPLE_SELECT); + else if (m_windowStyle & wxLB_EXTENDED) + XtSetArg (args[1], XmNselectionPolicy, XmEXTENDED_SELECT); + else + XtSetArg (args[1], XmNselectionPolicy, XmBROWSE_SELECT); + XtSetValues (listBox, args, 2); +*/ + + GetSize (&width2, &height2); + // Correct for randomly resized listbox - bad boy, Motif! + if (width1 != width2 || height1 != height2) + SetSize (-1, -1, width1, height1); } int wxListBox::Number () const { - return m_noItems; + return m_noItems; } // For single selection items only wxString wxListBox::GetStringSelection () const { - int sel = GetSelection (); - if (sel > -1) - return this->GetString (sel); - else - return wxString(""); + int sel = GetSelection (); + if (sel > -1) + return this->GetString (sel); + else + return wxString(""); } bool wxListBox::SetStringSelection (const wxString& s, bool flag) { - int sel = FindString (s); - if (sel > -1) + int sel = FindString (s); + if (sel > -1) { - SetSelection (sel, flag); - return TRUE; + SetSelection (sel, flag); + return TRUE; } - else - return FALSE; + else + return FALSE; } void wxListBox::Command (wxCommandEvent & event) { - if (event.m_extraLong) - SetSelection (event.m_commandInt); - else + if (event.m_extraLong) + SetSelection (event.m_commandInt); + else + { + Deselect (event.m_commandInt); + return; + } + ProcessCommand (event); +} + +void wxListBoxCallback (Widget w, XtPointer clientData, + XmListCallbackStruct * cbs) +{ +/* + if (cbs->reason == XmCR_EXTENDED_SELECT) + cout << "*** Extend select\n"; + else if (cbs->reason == XmCR_SINGLE_SELECT) + cout << "*** Single select\n"; + else if (cbs->reason == XmCR_MULTIPLE_SELECT) + cout << "*** Multiple select\n"; + else if (cbs->reason == XmCR_BROWSE_SELECT) + cout << "*** Browse select\n"; + + if (cbs->selection_type == XmMODIFICATION) + cout << "*** Modification\n"; + else if (cbs->selection_type == XmINITIAL) + cout << "*** Initial\n"; + else if (cbs->selection_type == XmADDITION) + cout << "*** Addition\n"; + */ + + wxListBox *item = (wxListBox *) clientData; + + if (item->m_inSetValue) + return; + + wxCommandEvent event (wxEVT_COMMAND_LISTBOX_SELECTED); + switch (cbs->reason) { - Deselect (event.m_commandInt); - return; + case XmCR_MULTIPLE_SELECT: + case XmCR_BROWSE_SELECT: + { + event.m_clientData = item->GetClientData (cbs->item_position - 1); + //event.commandString = item->GetStringSelection(); + event.m_commandInt = cbs->item_position - 1; + event.m_extraLong = TRUE; + event.SetEventObject(item); + item->ProcessCommand (event); + //delete[] event.commandString; // Let's not store the command string any more + break; + } + case XmCR_EXTENDED_SELECT: + { + switch (cbs->selection_type) + { + case XmINITIAL: + case XmADDITION: + case XmMODIFICATION: + { + event.m_clientData = item->GetClientData (cbs->item_position - 1); + event.m_commandInt = cbs->item_position - 1; + event.m_extraLong = TRUE; + event.SetEventObject(item); + item->ProcessCommand (event); + break; + } + } + break; + } } - ProcessCommand (event); } +/* Respond by getting the + * designated "default button" in the action area and activate it + * as if the user had selected it. + */ +void wxListBoxDefaultActionProc (Widget list_w, XtPointer client_data, XmListCallbackStruct * cbs) +{ + wxListBox *lbox = (wxListBox *) client_data; + + wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, lbox->GetId()); + event.SetEventObject( lbox ); + lbox->GetEventHandler()->ProcessEvent(event) ; +} + + diff --git a/src/motif/palette.cpp b/src/motif/palette.cpp index e5ec732673..58262fb1be 100644 --- a/src/motif/palette.cpp +++ b/src/motif/palette.cpp @@ -9,14 +9,46 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// +/* + * Colour map + * + * When constructed with the default constructor, we start from + * the wxApp::GetMainColormap, allocating additional read-only cells + * in Create(). The cells are freed on the next call to Create() + * or when the destructor is called. + */ + +/* Wolfram Gloger +I have implemented basic colormap support for the X11 versions of +wxWindows, notably wxPalette::Create(). The way I did it is to +allocate additional read-only color cells in the default colormap. In +general you will get arbitrary pixel values assigned to these new +cells and therefore I added a method wxColourMap::TransferBitmap() +which maps the pixel values 0..n to the real ones obtained with +Create(). This is only implemented for the popular case of 8-bit +depth. + +Allocating read-write color cells would involve installing a private +X11 colormap for a particular window, and AFAIK this is not +recommended; only the window manager should do this... Also, it is +not the functionality that wxPalette::Create() aims to provide. + */ + #ifdef __GNUG__ #pragma implementation "palette.h" #endif #include "wx/palette.h" +#include "wx/window.h" +#include "wx/app.h" +#include "wx/utils.h" + +#include +#include "wx/motif/private.h" #if !USE_SHARED_LIBRARIES IMPLEMENT_DYNAMIC_CLASS(wxPalette, wxGDIObject) +IMPLEMENT_DYNAMIC_CLASS(wxXPalette, wxObject) #endif /* @@ -24,14 +56,54 @@ IMPLEMENT_DYNAMIC_CLASS(wxPalette, wxGDIObject) * */ +wxXPalette::wxXPalette() +{ + m_cmap = (WXColormap) 0; + m_pix_array_n = 0; + m_pix_array = (unsigned long*) 0; + m_display = (WXDisplay*) 0; + m_destroyable = FALSE; +} + wxPaletteRefData::wxPaletteRefData() { - m_colormap = (WXColormap) 0; } wxPaletteRefData::~wxPaletteRefData() { - // TODO + XColor xcol; + Display *display = (Display*) NULL; + + wxNode *node, *next; + + for (node = m_palettes.First(); node; node = next) { + wxXPalette *c = (wxXPalette *)node->Data(); + unsigned long *pix_array = c->m_pix_array; + Colormap cmap = (Colormap) c->m_cmap; + bool destroyable = c->m_destroyable; + int pix_array_n = c->m_pix_array_n; + display = (Display*) c->m_display; + + if (pix_array_n > 0) + { +// XFreeColors(display, cmap, pix_array, pix_array_n, 0); + // Be careful not to free '0' pixels... + int i, j; + for(i=j=0; i i) XFreeColors(display, cmap, &pix_array[i], j-i, 0); + while(jNext(); + m_palettes.DeleteNode(node); + delete c; + } } wxPalette::wxPalette() @@ -51,17 +123,50 @@ bool wxPalette::Create(int n, const unsigned char *red, const unsigned char *gre { UnRef(); + if (!n) { + return FALSE; + } + m_refData = new wxPaletteRefData; - // TODO + XColor xcol; + Display* display = (Display*) wxGetDisplay(); + + unsigned long *pix_array; + Colormap cmap; + int pix_array_n; + + cmap = (Colormap) wxTheApp->GetMainColormap(display); + + pix_array = new unsigned long[n]; + if (!pix_array) + return FALSE; - return FALSE; + pix_array_n = n; + xcol.flags = DoRed | DoGreen | DoBlue; + for(int i = 0; i < n; i++) { + xcol.red = (unsigned short)red[i] << 8; + xcol.green = (unsigned short)green[i] << 8; + xcol.blue = (unsigned short)blue[i] << 8; + pix_array[i] = (XAllocColor(display, cmap, &xcol) == 0) ? 0 : xcol.pixel; + } + + wxXPalette *c = new wxXPalette; + + c->m_pix_array_n = pix_array_n; + c->m_pix_array = pix_array; + c->m_cmap = (WXColormap) cmap; + c->m_display = (WXDisplay*) display; + c->m_destroyable = FALSE; + M_PALETTEDATA->m_palettes.Append(c); + + return TRUE; } int wxPalette::GetPixel(const unsigned char red, const unsigned char green, const unsigned char blue) const { if ( !m_refData ) - return FALSE; + return FALSE; // TODO return FALSE; @@ -79,4 +184,170 @@ bool wxPalette::GetRGB(int index, unsigned char *red, unsigned char *green, unsi return FALSE; } +WXColormap wxPalette::GetXColormap(WXDisplay* display) const +{ + if (!M_PALETTEDATA || (M_PALETTEDATA->m_palettes.Number() == 0)) + return wxTheApp->GetMainColormap(display); + + wxNode* node = M_PALETTEDATA->m_palettes.First(); + if (!display && node) + { + wxXPalette* p = (wxXPalette*) node->Data(); + return p->m_cmap; + } + while (node) + { + wxXPalette* p = (wxXPalette*) node->Data(); + if (p->m_display == display) + return p->m_cmap; + + node = node->Next(); + } + + /* Make a new one: */ + wxXPalette *c = new wxXPalette; + wxXPalette *first = (wxXPalette *)M_PALETTEDATA->m_palettes.First()->Data(); + XColor xcol; + int pix_array_n = first->m_pix_array_n; + + c->m_pix_array_n = pix_array_n; + c->m_pix_array = new unsigned long[pix_array_n]; + c->m_display = display; + c->m_cmap = wxTheApp->GetMainColormap(display); + c->m_destroyable = FALSE; + + xcol.flags = DoRed | DoGreen | DoBlue; + int i; + for (i = 0; i < pix_array_n; i++) + { + xcol.pixel = first->m_pix_array[i]; + XQueryColor((Display*) first->m_display, (Colormap) first->m_cmap, &xcol); + c->m_pix_array[i] = + (XAllocColor((Display*) display, (Colormap) c->m_cmap, &xcol) == 0) ? 0 : xcol.pixel; + } + + // wxPalette* nonConstThis = (wxPalette*) this; + + M_PALETTEDATA->m_palettes.Append(c); + + return c->m_cmap; +} + +bool wxPalette::TransferBitmap(void *data, int depth, int size) +{ + switch(depth) { + case 8: + { + unsigned char *uptr = (unsigned char *)data; + int pix_array_n; + unsigned long *pix_array = GetXPixArray((Display*) wxGetDisplay(), &pix_array_n); + while(size-- > 0) + { + if((int)*uptr < pix_array_n) + *uptr = (unsigned char)pix_array[*uptr]; + uptr++; + } + + return TRUE; + } + default: + return FALSE; + } +} + +bool wxPalette::TransferBitmap8(unsigned char *data, unsigned long sz, + void *dest, unsigned int bpp) +{ + int pix_array_n; + unsigned long *pix_array = GetXPixArray((Display*) wxGetDisplay(), &pix_array_n); + switch(bpp) { + case 8: { + unsigned char *dptr = (unsigned char *)dest; + while(sz-- > 0) { + if((int)*data < pix_array_n) + *dptr = (unsigned char)pix_array[*data]; + data++; + dptr++; + } + break; + } + case 16: { + unsigned short *dptr = (unsigned short *)dest; + while(sz-- > 0) { + if((int)*data < pix_array_n) + *dptr = (unsigned short)pix_array[*data]; + data++; + dptr++; + } + break; + } + case 24: { + struct rgb24 { unsigned char r, g, b; } *dptr = (struct rgb24 *)dest; + while(sz-- > 0) { + if((int)*data < pix_array_n) { + dptr->r = pix_array[*data] & 0xFF; + dptr->g = (pix_array[*data] >> 8) & 0xFF; + dptr->b = (pix_array[*data] >> 16) & 0xFF; + } + data++; + dptr++; + } + break; + } + case 32: { + unsigned long *dptr = (unsigned long *)dest; + while(sz-- > 0) { + if((int)*data < pix_array_n) + *dptr = pix_array[*data]; + data++; + dptr++; + } + break; + } + default: + return FALSE; + } + return TRUE; +} + +unsigned long *wxPalette::GetXPixArray(WXDisplay *display, int *n) +{ + if (!M_PALETTEDATA) + return (unsigned long*) 0; + wxNode *node; + + for (node = M_PALETTEDATA->m_palettes.First(); node; node = node->Next()) + { + wxXPalette *c = (wxXPalette *)node->Data(); + if (c->m_display == display) + { + if (n) + *n = c->m_pix_array_n; + return c->m_pix_array; + } + } + + /* Not found; call GetXColormap, which will create it, then this again */ + if (GetXColormap(display)) + return GetXPixArray(display, n); + else + return (unsigned long*) 0; +} + +void wxPalette::PutXColormap(WXDisplay* display, WXColormap cm, bool dp) +{ + UnRef(); + + m_refData = new wxPaletteRefData; + + wxXPalette *c = new wxXPalette; + + c->m_pix_array_n = 0; + c->m_pix_array = (unsigned long*) NULL; + c->m_display = display; + c->m_cmap = cm; + c->m_destroyable = dp; + + M_PALETTEDATA->m_palettes.Append(c); +} diff --git a/src/motif/region.cpp b/src/motif/region.cpp index fcc58d3175..3a8f5603d0 100644 --- a/src/motif/region.cpp +++ b/src/motif/region.cpp @@ -1,10 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// // File: region.cpp // Purpose: Region class -// Author: Markus Holzem/Julian Smart/Julian Smart +// Author: Markus Holzem/Julian Smart // Created: Fri Oct 24 10:46:34 MET 1997 // RCS-ID: $Id$ -// Copyright: (c) 1997 Markus Holzem/Julian Smart/Julian Smart +// Copyright: (c) 1997 Markus Holzem/Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -15,6 +15,9 @@ #include "wx/region.h" #include "wx/gdicmn.h" +#include +// #include "wx/motif/private.h" + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject) IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject) @@ -28,19 +31,23 @@ class WXDLLEXPORT wxRegionRefData : public wxGDIRefData { public: wxRegionRefData() { + m_region = XCreateRegion(); } wxRegionRefData(const wxRegionRefData& data) { - // TODO + m_region = XCreateRegion(); + XUnionRegion(m_region, data.m_region, m_region); } ~wxRegionRefData() { - // TODO + XDestroyRegion(m_region); } + Region m_region; }; +#define M_REGION (((wxRegionRefData*)m_refData)->m_region) //----------------------------------------------------------------------------- // wxRegion @@ -51,26 +58,42 @@ public: */ wxRegion::wxRegion() { - m_refData = new wxRegionRefData; - // TODO create empty region } wxRegion::wxRegion(long x, long y, long w, long h) { m_refData = new wxRegionRefData; - // TODO create rect region + + XRectangle rect; + rect.x = x; + rect.y = y; + rect.width = w; + rect.height = h; + XUnionRectWithRegion(&rect, M_REGION, M_REGION); } wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight) { m_refData = new wxRegionRefData; - // TODO create rect region + + XRectangle rect; + rect.x = topLeft.x; + rect.y = topLeft.y; + rect.width = bottomRight.x - topLeft.x; + rect.height = bottomRight.y - topLeft.y; + XUnionRectWithRegion(&rect, M_REGION, M_REGION); } wxRegion::wxRegion(const wxRect& rect) { m_refData = new wxRegionRefData; - // TODO create rect region + + XRectangle rect1; + rect1.x = rect.x; + rect1.y = rect.y; + rect1.width = rect.width; + rect1.height = rect.height; + XUnionRectWithRegion(&rect1, M_REGION, M_REGION); } /*! @@ -104,16 +127,23 @@ bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op) } // If ref count is 1, that means it's 'ours' anyway so no action. - // TODO create rect region + Region rectRegion = XCreateRegion(); + + XRectangle rect; + rect.x = x; + rect.y = y; + rect.width = width; + rect.height = height; + XUnionRectWithRegion(&rect, rectRegion, rectRegion); int mode = 0; // TODO platform-specific code switch (op) { case wxRGN_AND: - // TODO + XIntersectRegion(M_REGION, rectRegion, M_REGION); break ; case wxRGN_OR: - // TODO + XUnionRegion(M_REGION, rectRegion, M_REGION); break ; case wxRGN_XOR: // TODO @@ -121,14 +151,12 @@ bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op) case wxRGN_DIFF: // TODO break ; - case wxRGN_COPY: + case wxRGN_COPY: // Don't have to do this one default: // TODO break ; } - // TODO do combine region - return FALSE; } @@ -151,10 +179,12 @@ bool wxRegion::Combine(const wxRegion& region, wxRegionOp op) switch (op) { case wxRGN_AND: - // TODO + XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region, + M_REGION); break ; case wxRGN_OR: - // TODO + XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region, + M_REGION); break ; case wxRGN_XOR: // TODO @@ -162,7 +192,7 @@ bool wxRegion::Combine(const wxRegion& region, wxRegionOp op) case wxRGN_DIFF: // TODO break ; - case wxRGN_COPY: + case wxRGN_COPY: // Don't have to do this one default: // TODO break ; @@ -186,7 +216,12 @@ bool wxRegion::Combine(const wxRect& rect, wxRegionOp op) void wxRegion::GetBox(long& x, long& y, long&w, long &h) const { if (m_refData) { - // TODO get box + XRectangle rect; + XClipBox(M_REGION, &rect); + x = rect.x; + y = rect.y; + w = rect.width; + h = rect.height; } else { x = y = w = h = 0; } @@ -202,8 +237,7 @@ wxRect wxRegion::GetBox() const // Is region empty? bool wxRegion::Empty() const { - // TODO - return FALSE; + return m_refData ? XEmptyRegion(M_REGION) : FALSE; } //----------------------------------------------------------------------------- @@ -228,11 +262,7 @@ wxRegionContain wxRegion::Contains(const wxPoint& pt) const if (!m_refData) return wxOutRegion; - // TODO. Return wxInRegion if within region. - if (0) - return wxInRegion; - else - return wxOutRegion; + return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion; } // Does the region contain the rectangle (x, y, w, h)? @@ -241,11 +271,11 @@ wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const if (!m_refData) return wxOutRegion; - // TODO. Return wxInRegion if within region. - if (0) - return wxInRegion; - else - return wxOutRegion; + switch (XRectInRegion(M_REGION, x, y, w, h)) { + case RectangleIn: return wxInRegion; + case RectanglePart: return wxPartRegion; + } + return wxOutRegion; } // Does the region contain the rectangle rect diff --git a/src/motif/window.cpp b/src/motif/window.cpp index 17a54f842d..c3a6018292 100644 --- a/src/motif/window.cpp +++ b/src/motif/window.cpp @@ -138,61 +138,61 @@ wxWindow::wxWindow() // Destructor wxWindow::~wxWindow() { - //// Motif-specific + //// Motif-specific - if (m_paintRegion) - XDestroyRegion ((Region) m_paintRegion); - m_paintRegion = (WXRegion) 0; + if (m_paintRegion) + XDestroyRegion ((Region) m_paintRegion); + m_paintRegion = (WXRegion) 0; - if (GetMainWidget()) - DetachWidget(GetMainWidget()); // Removes event handlers + if (GetMainWidget()) + DetachWidget(GetMainWidget()); // Removes event handlers - // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be) - if (m_drawingArea) - { - // Destroy children before destroying self - DestroyChildren(); + // If m_drawingArea, we're a fully-fledged window with drawing area, scrollbars etc. (what wxCanvas used to be) + if (m_drawingArea) + { + // Destroy children before destroying self + DestroyChildren(); - if (m_backingPixmap) - XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap); + if (m_backingPixmap) + XFreePixmap (XtDisplay ((Widget) GetMainWidget()), (Pixmap) m_backingPixmap); - Widget w = (Widget) m_drawingArea; - wxDeleteWindowFromTable(w); + Widget w = (Widget) m_drawingArea; + wxDeleteWindowFromTable(w); - if (w) - XtDestroyWidget(w); - m_mainWidget = (WXWidget) 0; + if (w) + XtDestroyWidget(w); + m_mainWidget = (WXWidget) 0; - // Only if we're _really_ a canvas (not a dialog box/panel) - if (m_scrolledWindow) - { - wxDeleteWindowFromTable((Widget) m_scrolledWindow); - } + // Only if we're _really_ a canvas (not a dialog box/panel) + if (m_scrolledWindow) + { + wxDeleteWindowFromTable((Widget) m_scrolledWindow); + } - if (m_hScrollBar) - { - XtUnmanageChild ((Widget) m_hScrollBar); - XtDestroyWidget ((Widget) m_hScrollBar); - } - if (m_vScrollBar) - { - XtUnmanageChild ((Widget) m_vScrollBar); - XtDestroyWidget ((Widget) m_vScrollBar); - } - if (m_scrolledWindow) - { - XtUnmanageChild ((Widget) m_scrolledWindow); - XtDestroyWidget ((Widget) m_scrolledWindow); - } + if (m_hScrollBar) + { + XtUnmanageChild ((Widget) m_hScrollBar); + XtDestroyWidget ((Widget) m_hScrollBar); + } + if (m_vScrollBar) + { + XtUnmanageChild ((Widget) m_vScrollBar); + XtDestroyWidget ((Widget) m_vScrollBar); + } + if (m_scrolledWindow) + { + XtUnmanageChild ((Widget) m_scrolledWindow); + XtDestroyWidget ((Widget) m_scrolledWindow); + } - if (m_borderWidget) - { - XtDestroyWidget ((Widget) m_borderWidget); - m_borderWidget = (WXWidget) 0; + if (m_borderWidget) + { + XtDestroyWidget ((Widget) m_borderWidget); + m_borderWidget = (WXWidget) 0; + } } - } - //// Generic stuff + //// Generic stuff // Have to delete constraints/sizer FIRST otherwise // sizers may try to look at deleted windows as they @@ -958,9 +958,13 @@ void wxWindow::SetFont(const wxFont& font) { m_windowFont = font; - if (!m_windowFont.Ok()) - return; - // TODO + Widget w = (Widget) GetMainWidget(); + if (w && m_windowFont.Ok()) + { + XtVaSetValues (w, + XmNfontList, (XmFontList) m_windowFont.GetFontList(1.0, XtDisplay(w)), + NULL); + } } void wxWindow::OnChar(wxKeyEvent& event) diff --git a/src/msw/makefile.nt b/src/msw/makefile.nt index ba06ea9590..c35b1ecb06 100644 --- a/src/msw/makefile.nt +++ b/src/msw/makefile.nt @@ -48,10 +48,14 @@ PERIPH_TARGET=xpm $(PERIPH_TARGET) PERIPH_CLEAN_TARGET=clean_xpm $(PERIPH_CLEAN_TARGET) !endif -GENDIR=..\generic -COMMDIR=..\common +# These are absolute paths, so that the compiler +# generates correct __FILE__ symbols for debugging. +# Otherwise you don't be able to double-click on a memory +# error to load that file. +GENDIR=$(WXDIR)\src\generic +COMMDIR=$(WXDIR)\src\common OLEDIR=ole -MSWDIR=. +MSWDIR=$(WXDIR)\src\msw DOCDIR = $(WXDIR)\docs diff --git a/src/msw/tbarmsw.cpp b/src/msw/tbarmsw.cpp index 84bf089014..91bed87c4b 100644 --- a/src/msw/tbarmsw.cpp +++ b/src/msw/tbarmsw.cpp @@ -46,7 +46,7 @@ /////// Non-Windows 95 implementation -#if !USE_IMAGE_LOADING_IN_MSW +#if !wxUSE_IMAGE_LOADING_IN_MSW #error If wxUSE_IMAGE_LOADING_IN_MSW is set to 0, then wxUSE_BUTTONBAR must be set to 0 too. #endif diff --git a/src/msw/xfspline.inc b/src/msw/xfspline.inc index 792cf3e23f..6e98adb455 100644 --- a/src/msw/xfspline.inc +++ b/src/msw/xfspline.inc @@ -17,7 +17,7 @@ */ -#if USE_SPLINES +#if wxUSE_SPLINES ////#define wx_round(a) (int)((a)+.5) //#define wx_round(a) (a) @@ -37,7 +37,7 @@ class wxSpline: public wxObject void wx_draw_open_spline(wxDC *dc, wxSpline *spline); -#if USE_POSTSCRIPT +#if wxUSE_POSTSCRIPT void wx_draw_open_spline_ps(wxPostScriptDC *dc, wxSpline *s); #endif @@ -122,7 +122,7 @@ void wx_draw_open_spline(wxDC *dc, wxSpline *spline) } -#if USE_POSTSCRIPT +#if wxUSE_POSTSCRIPT void wx_draw_open_spline_ps(wxPostScriptDC *dc, wxSpline *s) { double a, b, c, d, x1, y1, x2, y2, x3, y3; @@ -307,7 +307,7 @@ void wxSpline::DeletePoints(void) delete points; } -#if USE_POSTSCRIPT +#if wxUSE_POSTSCRIPT // Make a 3-point spline void wxPostScriptDC::DrawSpline(long x1, long y1, long x2, long y2, long x3, long y3) @@ -349,7 +349,7 @@ void wxPostScriptDC::DrawSpline(int n, wxPoint points[]) } -#endif // USE_POSTSCRIPT +#endif // wxUSE_POSTSCRIPT -#endif // USE_SPLINES +#endif // wxUSE_SPLINES diff --git a/src/stubs/cursor.cpp b/src/stubs/cursor.cpp index f5cc609f7e..4333364c93 100644 --- a/src/stubs/cursor.cpp +++ b/src/stubs/cursor.cpp @@ -46,7 +46,7 @@ wxCursor::wxCursor(const char WXUNUSED(bits)[], int WXUNUSED(width), int WXUNUSE wxCursor::wxCursor(const wxString& cursor_file, long flags, int hotSpotX, int hotSpotY) { - m_refData = new wxIconRefData; + m_refData = new wxCursorRefData; // TODO: create cursor from a file } @@ -54,7 +54,7 @@ wxCursor::wxCursor(const wxString& cursor_file, long flags, int hotSpotX, int ho // Cursors by stock number wxCursor::wxCursor(int cursor_type) { - m_refData = new wxIconRefData; + m_refData = new wxCursorRefData; /* TODO switch (cursor_type) diff --git a/utils/ogl/src/basic.cpp b/utils/ogl/src/basic.cpp index 33d25bdf21..1dff73fedc 100644 --- a/utils/ogl/src/basic.cpp +++ b/utils/ogl/src/basic.cpp @@ -127,6 +127,12 @@ void wxShapeEvtHandler::OnDrawContents(wxDC& dc) m_previousHandler->OnDrawContents(dc); } +void wxShapeEvtHandler::OnDrawBranches(wxDC& dc, bool erase) +{ + if (m_previousHandler) + m_previousHandler->OnDrawBranches(dc, erase); +} + void wxShapeEvtHandler::OnSize(double x, double y) { if (m_previousHandler) @@ -276,7 +282,7 @@ wxShape::wxShape(wxShapeCanvas *can) m_visible = FALSE; m_clientData = NULL; m_selected = FALSE; - m_attachmentMode = FALSE; + m_attachmentMode = ATTACHMENT_MODE_NONE; m_spaceAttachments = TRUE; m_disableLabel = FALSE; m_fixedWidth = FALSE; @@ -297,6 +303,10 @@ wxShape::wxShape(wxShapeCanvas *can) m_maintainAspectRatio = FALSE; m_highlighted = FALSE; m_rotation = 0.0; + m_branchNeckLength = 10; + m_branchStemLength = 10; + m_branchSpacing = 10; + m_branchStyle = BRANCHING_ATTACHMENT_NORMAL; // Set up a default region. Much of the above will be put into // the region eventually (the duplication is for compatibility) @@ -541,7 +551,6 @@ bool wxShape::HitTest(double x, double y, int *attachment, double *distance) int nearest_attachment = 0; - // If within the bounding box, check the attachment points // within the object. @@ -550,10 +559,13 @@ bool wxShape::HitTest(double x, double y, int *attachment, double *distance) int n = GetNumberOfAttachments(); double nearest = 999999.0; + // GetAttachmentPosition[Edge] takes a logical attachment position, + // i.e. if it's rotated through 90%, position 0 is East-facing. + for (int i = 0; i < n; i++) { double xp, yp; - if (GetAttachmentPosition(i, &xp, &yp)) + if (GetAttachmentPositionEdge(i, &xp, &yp)) { double l = (double)sqrt(((xp - x) * (xp - x)) + ((yp - y) * (yp - y))); @@ -1038,7 +1050,8 @@ void wxShape::DrawLinks(wxDC& dc, int attachment, bool recurse) // This is the default, rectangular implementation. bool wxShape::AttachmentSortTest(int attachmentPoint, const wxRealPoint& pt1, const wxRealPoint& pt2) { - switch (attachmentPoint) + int physicalAttachment = LogicalToPhysicalAttachment(attachmentPoint); + switch (physicalAttachment) { case 0: case 2: @@ -1060,7 +1073,7 @@ bool wxShape::AttachmentSortTest(int attachmentPoint, const wxRealPoint& pt1, co bool wxShape::MoveLineToNewAttachment(wxDC& dc, wxLineShape *to_move, double x, double y) { - if (!GetAttachmentMode()) + if (GetAttachmentMode() == ATTACHMENT_MODE_NONE) return FALSE; int newAttachment, oldAttachment; @@ -1502,6 +1515,7 @@ void wxShape::Draw(wxDC& dc) GetEventHandler()->OnDraw(dc); GetEventHandler()->OnDrawContents(dc); GetEventHandler()->OnDrawControlPoints(dc); + GetEventHandler()->OnDrawBranches(dc); } } @@ -1535,6 +1549,7 @@ void wxShape::Erase(wxDC& dc) { GetEventHandler()->OnErase(dc); GetEventHandler()->OnEraseControlPoints(dc); + GetEventHandler()->OnDrawBranches(dc, TRUE); } void wxShape::EraseContents(wxDC& dc) @@ -1758,6 +1773,14 @@ void wxShape::WriteAttributes(wxExpr *clause) if (m_rotation != 0.0) clause->AddAttributeValue("rotation", m_rotation); + if (!this->IsKindOf(CLASSINFO(wxLineShape))) + { + clause->AddAttributeValue("neck_length", (long) m_branchNeckLength); + clause->AddAttributeValue("stem_length", (long) m_branchStemLength); + clause->AddAttributeValue("branch_spacing", (long) m_branchSpacing); + clause->AddAttributeValue("branch_style", (long) m_branchStyle); + } + // Write user-defined attachment points, if any if (m_attachmentPoints.Number() > 0) { @@ -1912,7 +1935,7 @@ void wxShape::ReadAttributes(wxExpr *clause) int pen_width = 1; int pen_style = wxSOLID; int brush_style = wxSOLID; - m_attachmentMode = FALSE; + m_attachmentMode = ATTACHMENT_MODE_NONE; clause->GetAttributeValue("pen_colour", pen_string); clause->GetAttributeValue("text_colour", m_textColourName); @@ -1928,7 +1951,7 @@ void wxShape::ReadAttributes(wxExpr *clause) int iVal = (int) m_attachmentMode; clause->GetAttributeValue("use_attachments", iVal); - m_attachmentMode = (iVal != 0); + m_attachmentMode = iVal; clause->GetAttributeValue("sensitivity", m_sensitivity); @@ -1947,6 +1970,20 @@ void wxShape::ReadAttributes(wxExpr *clause) clause->GetAttributeValue("format_mode", m_formatMode); clause->GetAttributeValue("shadow_mode", m_shadowMode); + iVal = m_branchNeckLength; + clause->GetAttributeValue("neck_length", iVal); + m_branchNeckLength = iVal; + + iVal = m_branchStemLength; + clause->GetAttributeValue("stem_length", iVal); + m_branchStemLength = iVal; + + iVal = m_branchSpacing; + clause->GetAttributeValue("branch_spacing", iVal); + m_branchSpacing = iVal; + + clause->GetAttributeValue("branch_style", m_branchStyle); + iVal = (int) m_centreResize; clause->GetAttributeValue("centre_resize", iVal); m_centreResize = (iVal != 0); @@ -2251,6 +2288,10 @@ void wxShape::Copy(wxShape& copy) copy.m_shadowOffsetY = m_shadowOffsetY; copy.m_shadowBrush = m_shadowBrush; + copy.m_branchNeckLength = m_branchNeckLength; + copy.m_branchStemLength = m_branchStemLength; + copy.m_branchSpacing = m_branchSpacing; + // Copy text regions copy.ClearRegions(); wxNode *node = m_regions.First(); @@ -2631,12 +2672,20 @@ bool wxShape::AttachmentIsValid(int attachment) const bool wxShape::GetAttachmentPosition(int attachment, double *x, double *y, int nth, int no_arcs, wxLineShape *line) { - if (!m_attachmentMode) + if (m_attachmentMode == ATTACHMENT_MODE_NONE) { *x = m_xpos; *y = m_ypos; return TRUE; } - else + else if (m_attachmentMode == ATTACHMENT_MODE_BRANCHING) + { + wxRealPoint pt, stemPt; + GetBranchingAttachmentPoint(attachment, nth, pt, stemPt); + *x = pt.x; + *y = pt.y; + return TRUE; + } + else if (m_attachmentMode == ATTACHMENT_MODE_EDGE) { if (m_attachmentPoints.Number() > 0) { @@ -2667,8 +2716,10 @@ bool wxShape::GetAttachmentPosition(int attachment, double *x, double *y, bool isEnd = (line && line->IsEnd(this)); + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + // Simplified code - switch (attachment) + switch (physicalAttachment) { case 0: { @@ -2704,7 +2755,7 @@ bool wxShape::GetAttachmentPosition(int attachment, double *x, double *y, } default: { - return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); + return FALSE; break; } } @@ -2855,3 +2906,365 @@ int wxShape::GetLinePosition(wxLineShape* line) return 0; } +// +// |________| +// | <- root +// | <- neck +// shoulder1 ->---------<- shoulder2 +// | | | | | +// <- branching attachment point N-1 + +// This function gets information about where branching connections go. +// Returns FALSE if there are no lines at this attachment. +bool wxShape::GetBranchingAttachmentInfo(int attachment, wxRealPoint& root, wxRealPoint& neck, + wxRealPoint& shoulder1, wxRealPoint& shoulder2) +{ + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + // Number of lines at this attachment. + int lineCount = GetAttachmentLineCount(attachment); + + if (lineCount == 0) + return FALSE; + + int totalBranchLength = m_branchSpacing * (lineCount - 1); + + root = GetBranchingAttachmentRoot(attachment); + + // Assume that we have attachment points 0 to 3: top, right, bottom, left. + switch (physicalAttachment) + { + case 0: + { + neck.x = GetX(); + neck.y = root.y - m_branchNeckLength; + + shoulder1.x = root.x - (totalBranchLength/2.0) ; + shoulder2.x = root.x + (totalBranchLength/2.0) ; + + shoulder1.y = neck.y; + shoulder2.y = neck.y; + break; + } + case 1: + { + neck.x = root.x + m_branchNeckLength; + neck.y = root.y; + + shoulder1.x = neck.x ; + shoulder2.x = neck.x ; + + shoulder1.y = neck.y - (totalBranchLength/2.0) ; + shoulder2.y = neck.y + (totalBranchLength/2.0) ; + break; + } + case 2: + { + neck.x = GetX(); + neck.y = root.y + m_branchNeckLength; + + shoulder1.x = root.x - (totalBranchLength/2.0) ; + shoulder2.x = root.x + (totalBranchLength/2.0) ; + + shoulder1.y = neck.y; + shoulder2.y = neck.y; + break; + } + case 3: + { + neck.x = root.x - m_branchNeckLength; + neck.y = root.y ; + + shoulder1.x = neck.x ; + shoulder2.x = neck.x ; + + shoulder1.y = neck.y - (totalBranchLength/2.0) ; + shoulder2.y = neck.y + (totalBranchLength/2.0) ; + break; + } + default: + { + wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentInfo." ); + break; + } + } + return TRUE; +} + +// n is the number of the adjoining line, from 0 to N-1 where N is the number of lines +// at this attachment point. +// Get the attachment point where the arc joins the stem, and also the point where the +// the stem meets the shoulder. +bool wxShape::GetBranchingAttachmentPoint(int attachment, int n, wxRealPoint& pt, wxRealPoint& stemPt) +{ + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + wxRealPoint root, neck, shoulder1, shoulder2; + GetBranchingAttachmentInfo(attachment, root, neck, shoulder1, shoulder2); + + // Assume that we have attachment points 0 to 3: top, right, bottom, left. + switch (physicalAttachment) + { + case 0: + { + pt.y = neck.y - m_branchStemLength; + pt.x = shoulder1.x + n*m_branchSpacing; + + stemPt.x = pt.x; + stemPt.y = neck.y; + break; + } + case 2: + { + pt.y = neck.y + m_branchStemLength; + pt.x = shoulder1.x + n*m_branchSpacing; + + stemPt.x = pt.x; + stemPt.y = neck.y; + break; + } + case 1: + { + pt.x = neck.x + m_branchStemLength; + pt.y = shoulder1.y + n*m_branchSpacing; + + stemPt.x = neck.x; + stemPt.y = pt.y; + break; + } + case 3: + { + pt.x = neck.x - m_branchStemLength; + pt.y = shoulder1.y + n*m_branchSpacing; + + stemPt.x = neck.x; + stemPt.y = pt.y; + break; + } + default: + { + wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentPoint." ); + break; + } + } + + return TRUE; +} + +// Get the number of lines at this attachment position. +int wxShape::GetAttachmentLineCount(int attachment) const +{ + int count = 0; + wxNode* node = m_lines.First(); + while (node) + { + wxLineShape* lineShape = (wxLineShape*) node->Data(); + if ((lineShape->GetFrom() == this) && (lineShape->GetAttachmentFrom() == attachment)) + count ++; + else if ((lineShape->GetTo() == this) && (lineShape->GetAttachmentTo() == attachment)) + count ++; + + node = node->Next(); + } + return count; +} + +// This function gets the root point at the given attachment. +wxRealPoint wxShape::GetBranchingAttachmentRoot(int attachment) +{ + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + wxRealPoint root; + + double width, height; + GetBoundingBoxMax(& width, & height); + + // Assume that we have attachment points 0 to 3: top, right, bottom, left. + switch (physicalAttachment) + { + case 0: + { + root.x = GetX() ; + root.y = GetY() - height/2.0; + break; + } + case 1: + { + root.x = GetX() + width/2.0; + root.y = GetY() ; + break; + } + case 2: + { + root.x = GetX() ; + root.y = GetY() + height/2.0; + break; + } + case 3: + { + root.x = GetX() - width/2.0; + root.y = GetY() ; + break; + } + default: + { + wxFAIL_MSG( "Unrecognised attachment point in GetBranchingAttachmentRoot." ); + break; + } + } + return root; +} + +// Draw or erase the branches (not the actual arcs though) +void wxShape::OnDrawBranches(wxDC& dc, int attachment, bool erase) +{ + int count = GetAttachmentLineCount(attachment); + if (count == 0) + return; + + wxRealPoint root, neck, shoulder1, shoulder2; + GetBranchingAttachmentInfo(attachment, root, neck, shoulder1, shoulder2); + + if (erase) + { + dc.SetPen(*wxWHITE_PEN); + dc.SetBrush(*wxWHITE_BRUSH); + } + else + { + dc.SetPen(*wxBLACK_PEN); + dc.SetBrush(*wxBLACK_BRUSH); + } + + // Draw neck + dc.DrawLine((long) root.x, (long) root.y, (long) neck.x, (long) neck.y); + + if (count > 1) + { + // Draw shoulder-to-shoulder line + dc.DrawLine((long) shoulder1.x, (long) shoulder1.y, (long) shoulder2.x, (long) shoulder2.y); + } + // Draw all the little branches + int i; + for (i = 0; i < count; i++) + { + wxRealPoint pt, stemPt; + GetBranchingAttachmentPoint(attachment, i, pt, stemPt); + dc.DrawLine((long) stemPt.x, (long) stemPt.y, (long) pt.x, (long) pt.y); + + if (GetBranchStyle() & BRANCHING_ATTACHMENT_BLOB) + { + long blobSize=6; +// dc.DrawEllipse((long) (stemPt.x + 0.5 - (blobSize/2.0)), (long) (stemPt.y + 0.5 - (blobSize/2.0)), blobSize, blobSize); + dc.DrawEllipse((long) (stemPt.x - (blobSize/2.0)), (long) (stemPt.y - (blobSize/2.0)), blobSize, blobSize); + } + } +} + +// Draw or erase the branches (not the actual arcs though) +void wxShape::OnDrawBranches(wxDC& dc, bool erase) +{ + if (m_attachmentMode != ATTACHMENT_MODE_BRANCHING) + return; + + int count = GetNumberOfAttachments(); + int i; + for (i = 0; i < count; i++) + OnDrawBranches(dc, i, erase); +} + +// Only get the attachment position at the _edge_ of the shape, ignoring +// branching mode. This is used e.g. to indicate the edge of interest, not the point +// on the attachment branch. +bool wxShape::GetAttachmentPositionEdge(int attachment, double *x, double *y, + int nth, int no_arcs, wxLineShape *line) +{ + int oldMode = m_attachmentMode; + + // Calculate as if to edge, not branch + if (m_attachmentMode == ATTACHMENT_MODE_BRANCHING) + m_attachmentMode = ATTACHMENT_MODE_EDGE; + bool success = GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); + m_attachmentMode = oldMode; + + return success; +} + +// Rotate the standard attachment point from physical (0 is always North) +// to logical (0 -> 1 if rotated by 90 degrees) +int wxShape::PhysicalToLogicalAttachment(int physicalAttachment) const +{ + const double pi = 3.1415926535897932384626433832795 ; + int i; + if (oglRoughlyEqual(GetRotation(), 0.0)) + { + i = physicalAttachment; + } + else if (oglRoughlyEqual(GetRotation(), (pi/2.0))) + { + i = physicalAttachment - 1; + } + else if (oglRoughlyEqual(GetRotation(), pi)) + { + i = physicalAttachment - 2; + } + else if (oglRoughlyEqual(GetRotation(), (3.0*pi/2.0))) + { + i = physicalAttachment - 3; + } + else + // Can't handle -- assume the same. + return physicalAttachment; + + if (i < 0) + i += 4; + + return i; +} + +// Rotate the standard attachment point from logical +// to physical (0 is always North) +int wxShape::LogicalToPhysicalAttachment(int logicalAttachment) const +{ + const double pi = 3.1415926535897932384626433832795 ; + int i; + if (oglRoughlyEqual(GetRotation(), 0.0)) + { + i = logicalAttachment; + } + else if (oglRoughlyEqual(GetRotation(), (pi/2.0))) + { + i = logicalAttachment + 1; + } + else if (oglRoughlyEqual(GetRotation(), pi)) + { + i = logicalAttachment + 2; + } + else if (oglRoughlyEqual(GetRotation(), (3.0*pi/2.0))) + { + i = logicalAttachment + 3; + } + else + // Can't handle -- assume the same. + return logicalAttachment; + + if (i > 3) + i -= 4; + + return i; +} + +void wxShape::Rotate(double WXUNUSED(x), double WXUNUSED(y), double theta) +{ + const double pi = 3.1415926535897932384626433832795 ; + m_rotation = theta; + if (m_rotation < 0.0) + { + m_rotation += 2*pi; + } + else if (m_rotation > 2*pi) + { + m_rotation -= 2*pi; + } +} + diff --git a/utils/ogl/src/basic.h b/utils/ogl/src/basic.h index 52b78d16ed..ad8d5fb096 100644 --- a/utils/ogl/src/basic.h +++ b/utils/ogl/src/basic.h @@ -94,6 +94,15 @@ #define OP_ALL (OP_CLICK_LEFT | OP_CLICK_RIGHT | OP_DRAG_LEFT | OP_DRAG_RIGHT) +// Attachment modes +#define ATTACHMENT_MODE_NONE 0 +#define ATTACHMENT_MODE_EDGE 1 +#define ATTACHMENT_MODE_BRANCHING 2 + +// Sub-modes for branching attachment mode +#define BRANCHING_ATTACHMENT_NORMAL 1 +#define BRANCHING_ATTACHMENT_BLOB 2 + class wxShapeTextLine; class wxShapeCanvas; class wxLineShape; @@ -127,6 +136,7 @@ class wxShapeEvtHandler: public wxObject virtual void OnDelete(); virtual void OnDraw(wxDC& dc); virtual void OnDrawContents(wxDC& dc); + virtual void OnDrawBranches(wxDC& dc, bool erase = FALSE); virtual void OnMoveLinks(wxDC& dc); virtual void OnErase(wxDC& dc); virtual void OnEraseContents(wxDC& dc); @@ -274,8 +284,8 @@ class wxShape: public wxShapeEvtHandler inline wxList& GetLines() const { return (wxList&) m_lines; } inline void SetDisableLabel(bool flag) { m_disableLabel = flag; } inline bool GetDisableLabel() const { return m_disableLabel; } - inline void SetAttachmentMode(bool flag) { m_attachmentMode = flag; } - inline bool GetAttachmentMode() const { return m_attachmentMode; } + inline void SetAttachmentMode(int mode) { m_attachmentMode = mode; } + inline int GetAttachmentMode() const { return m_attachmentMode; } inline void SetId(long i) { m_id = i; } inline long GetId() const { return m_id; } @@ -382,6 +392,12 @@ class wxShape: public wxShapeEvtHandler virtual int GetNumberOfAttachments() const; virtual bool AttachmentIsValid(int attachment) const; + // Only get the attachment position at the _edge_ of the shape, ignoring + // branching mode. This is used e.g. to indicate the edge of interest, not the point + // on the attachment branch. + virtual bool GetAttachmentPositionEdge(int attachment, double *x, double *y, + int nth = 0, int no_arcs = 1, wxLineShape *line = NULL); + // Assuming the attachment lies along a vertical or horizontal line, // calculate the position on that point. virtual wxRealPoint CalcSimpleAttachment(const wxRealPoint& pt1, const wxRealPoint& pt2, @@ -408,6 +424,59 @@ class wxShape: public wxShapeEvtHandler // Can override this to prevent or intercept line reordering. virtual void OnChangeAttachment(int attachment, wxLineShape* line, wxList& ordering); + //// New banching attachment code, 24/9/98 + + // + // |________| + // | <- root + // | <- neck + // shoulder1 ->---------<- shoulder2 + // | | | | |<- stem + // <- branching attachment point N-1 + + // This function gets the root point at the given attachment. + virtual wxRealPoint GetBranchingAttachmentRoot(int attachment); + + // This function gets information about where branching connections go (calls GetBranchingAttachmentRoot) + virtual bool GetBranchingAttachmentInfo(int attachment, wxRealPoint& root, wxRealPoint& neck, + wxRealPoint& shoulder1, wxRealPoint& shoulder2); + + // n is the number of the adjoining line, from 0 to N-1 where N is the number of lines + // at this attachment point. + // attachmentPoint is where the arc meets the stem, and stemPoint is where the stem meets the + // shoulder. + virtual bool GetBranchingAttachmentPoint(int attachment, int n, wxRealPoint& attachmentPoint, + wxRealPoint& stemPoint); + + // Get the number of lines at this attachment position. + virtual int GetAttachmentLineCount(int attachment) const; + + // Draw the branches (not the actual arcs though) + virtual void OnDrawBranches(wxDC& dc, int attachment, bool erase = FALSE); + virtual void OnDrawBranches(wxDC& dc, bool erase = FALSE); + + // Branching attachment settings + inline void SetBranchNeckLength(int len) { m_branchNeckLength = len; } + inline int GetBranchNeckLength() const { return m_branchNeckLength; } + + inline void SetBranchStemLength(int len) { m_branchStemLength = len; } + inline int GetBranchStemLength() const { return m_branchStemLength; } + + inline void SetBranchSpacing(int len) { m_branchSpacing = len; } + inline int GetBranchSpacing() const { return m_branchSpacing; } + + // Further detail on branching style, e.g. blobs on interconnections + inline void SetBranchStyle(long style) { m_branchStyle = style; } + inline long GetBranchStyle() const { return m_branchStyle; } + + // Rotate the standard attachment point from physical (0 is always North) + // to logical (0 -> 1 if rotated by 90 degrees) + virtual int PhysicalToLogicalAttachment(int physicalAttachment) const; + + // Rotate the standard attachment point from logical + // to physical (0 is always North) + virtual int LogicalToPhysicalAttachment(int logicalAttachment) const; + // This is really to distinguish between lines and other images. // For lines, want to pass drag to canvas, since lines tend to prevent // dragging on a canvas (they get in the way.) @@ -426,11 +495,8 @@ class wxShape: public wxShapeEvtHandler // handler data if any. Calls the virtual Copy function. void CopyWithHandler(wxShape& copy); - // Rotate about the given axis by the given amount in radians - // (does nothing for most objects) - // But even non-rotating objects should record their notional - // rotation in case it's important (e.g. in dog-leg code). - virtual inline void Rotate(double WXUNUSED(x), double WXUNUSED(y), double theta) { m_rotation = theta; } + // Rotate about the given axis by the given amount in radians. + virtual void Rotate(double x, double y, double theta); virtual inline double GetRotation() const { return m_rotation; } void ClearAttachments(); @@ -468,7 +534,8 @@ class wxShape: public wxShapeEvtHandler double m_rotation; int m_sensitivity; bool m_draggable; - bool m_attachmentMode; // TRUE if using attachments, FALSE otherwise + int m_attachmentMode; // 0 for no attachments, 1 if using normal attachments, + // 2 for branching attachments bool m_spaceAttachments; // TRUE if lines at one side should be spaced bool m_fixedWidth; bool m_fixedHeight; @@ -485,6 +552,10 @@ class wxShape: public wxShapeEvtHandler int m_textMarginY; wxString m_regionName; bool m_maintainAspectRatio; + int m_branchNeckLength; + int m_branchStemLength; + int m_branchSpacing; + long m_branchStyle; }; class wxPolygonShape: public wxShape diff --git a/utils/ogl/src/basic2.cpp b/utils/ogl/src/basic2.cpp index e54c84bbeb..40b86bf5f3 100644 --- a/utils/ogl/src/basic2.cpp +++ b/utils/ogl/src/basic2.cpp @@ -308,7 +308,7 @@ bool wxPolygonShape::HitTest(double x, double y, int *attachment, double *distan for (i = 0; i < n; i++) { double xp, yp; - if (GetAttachmentPosition(i, &xp, &yp)) + if (GetAttachmentPositionEdge(i, &xp, &yp)) { double l = (double)sqrt(((xp - x) * (xp - x)) + ((yp - y) * (yp - y))); @@ -439,7 +439,7 @@ bool wxPolygonShape::GetPerimeterPoint(double x1, double y1, // and we would want to connect to a point on that vertical -- // oglFindEndForPolyline can't cope with this (the arrow // gets drawn to the wrong place). - if ((!m_attachmentMode) && (x1 == x2)) + if ((m_attachmentMode == ATTACHMENT_MODE_NONE) && (x1 == x2)) { // Look for the point we'd be connecting to. This is // a heuristic... @@ -785,7 +785,7 @@ int wxPolygonShape::GetNumberOfAttachments() const bool wxPolygonShape::GetAttachmentPosition(int attachment, double *x, double *y, int nth, int no_arcs, wxLineShape *line) { - if (m_attachmentMode && m_points && attachment < m_points->Number()) + if ((m_attachmentMode == ATTACHMENT_MODE_EDGE) && m_points && attachment < m_points->Number()) { wxRealPoint *point = (wxRealPoint *)m_points->Nth(attachment)->Data(); *x = point->x + m_xpos; @@ -989,61 +989,7 @@ int wxRectangleShape::GetNumberOfAttachments() const bool wxRectangleShape::GetAttachmentPosition(int attachment, double *x, double *y, int nth, int no_arcs, wxLineShape *line) { - if (m_attachmentMode) - { - double top = (double)(m_ypos + m_height/2.0); - double bottom = (double)(m_ypos - m_height/2.0); - double left = (double)(m_xpos - m_width/2.0); - double right = (double)(m_xpos + m_width/2.0); - - bool isEnd = (line && line->IsEnd(this)); - - // Simplified code - switch (attachment) - { - case 0: - { - wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(right, bottom), - nth, no_arcs, line); - - *x = pt.x; *y = pt.y; - break; - } - case 1: - { - wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(right, bottom), wxRealPoint(right, top), - nth, no_arcs, line); - - *x = pt.x; *y = pt.y; - break; - } - case 2: - { - wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, top), wxRealPoint(right, top), - nth, no_arcs, line); - - *x = pt.x; *y = pt.y; - break; - } - case 3: - { - wxRealPoint pt = CalcSimpleAttachment(wxRealPoint(left, bottom), wxRealPoint(left, top), - nth, no_arcs, line); - - *x = pt.x; *y = pt.y; - break; - } - default: - { - return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); - break; - } - } - - return TRUE; - } - else - { *x = m_xpos; *y = m_ypos; return TRUE; } + return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); } // Text object (no box) @@ -1179,13 +1125,19 @@ int wxEllipseShape::GetNumberOfAttachments() const bool wxEllipseShape::GetAttachmentPosition(int attachment, double *x, double *y, int nth, int no_arcs, wxLineShape *line) { - if (m_attachmentMode) + if (m_attachmentMode == ATTACHMENT_MODE_BRANCHING) + return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line); + + if (m_attachmentMode != ATTACHMENT_MODE_NONE) { double top = (double)(m_ypos + m_height/2.0); double bottom = (double)(m_ypos - m_height/2.0); double left = (double)(m_xpos - m_width/2.0); double right = (double)(m_xpos + m_width/2.0); - switch (attachment) + + int physicalAttachment = LogicalToPhysicalAttachment(attachment); + + switch (physicalAttachment) { case 0: { diff --git a/utils/ogl/src/divided.cpp b/utils/ogl/src/divided.cpp index 73fbe83434..9768075e72 100644 --- a/utils/ogl/src/divided.cpp +++ b/utils/ogl/src/divided.cpp @@ -186,7 +186,7 @@ bool wxDividedShape::GetAttachmentPosition(int attachment, double *x, double *y, wxLineShape *line) { int totalNumberAttachments = (GetRegions().Number() * 2) + 2; - if (!GetAttachmentMode() || (attachment >= totalNumberAttachments)) + if ((GetAttachmentMode() == ATTACHMENT_MODE_NONE) || (attachment >= totalNumberAttachments)) { return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs); } diff --git a/utils/ogl/src/drawn.cpp b/utils/ogl/src/drawn.cpp index f6d8f33a98..498448efab 100644 --- a/utils/ogl/src/drawn.cpp +++ b/utils/ogl/src/drawn.cpp @@ -1219,7 +1219,7 @@ bool wxOpPolyDraw::GetPerimeterPoint(double x1, double y1, double x2, double y2, double *x3, double *y3, double xOffset, double yOffset, - bool attachmentMode) + int attachmentMode) { int n = m_noPoints; @@ -1227,7 +1227,7 @@ bool wxOpPolyDraw::GetPerimeterPoint(double x1, double y1, // and we would want to connect to a point on that vertical -- // oglFindEndForPolyline can't cope with this (the arrow // gets drawn to the wrong place). - if ((!attachmentMode) && (x1 == x2)) + if ((attachmentMode == ATTACHMENT_MODE_NONE) && (x1 == x2)) { // Look for the point we'd be connecting to. This is // a heuristic... diff --git a/utils/ogl/src/drawnp.h b/utils/ogl/src/drawnp.h index ab5ef12631..991f5dc823 100644 --- a/utils/ogl/src/drawnp.h +++ b/utils/ogl/src/drawnp.h @@ -79,7 +79,7 @@ public: double x2, double y2, double *x3, double *y3, double xOffset, double yOffset, - bool attachmentMode) + int attachmentMode) { return FALSE; } protected: @@ -191,7 +191,7 @@ public: double x2, double y2, double *x3, double *y3, double xOffset, double yOffset, - bool attachmentMode); + int attachmentMode); public: wxRealPoint* m_points; diff --git a/utils/ogl/src/lines.cpp b/utils/ogl/src/lines.cpp index 56508e4c43..d03b2f401a 100644 --- a/utils/ogl/src/lines.cpp +++ b/utils/ogl/src/lines.cpp @@ -1065,7 +1065,7 @@ void wxLineShape::OnMoveLink(wxDC& dc, bool moveControlPoints) // if (moveControlPoints && m_lineControlPoints && !(x_offset == 0.0 && y_offset == 0.0)) // Only move control points if it's a self link. And only works if attachment mode is ON. - if ((m_from == m_to) && m_from->GetAttachmentMode() && moveControlPoints && m_lineControlPoints && !(x_offset == 0.0 && y_offset == 0.0)) + if ((m_from == m_to) && (m_from->GetAttachmentMode() != ATTACHMENT_MODE_NONE) && moveControlPoints && m_lineControlPoints && !(x_offset == 0.0 && y_offset == 0.0)) { wxNode *node = m_lineControlPoints->First(); while (node) @@ -1110,7 +1110,7 @@ void wxLineShape::FindLineEndPoints(double *fromX, double *fromY, double *toX, d if (m_lineControlPoints->Number() > 2) { - if (m_from->GetAttachmentMode()) + if (m_from->GetAttachmentMode() != ATTACHMENT_MODE_NONE) { int nth, no_arcs; FindNth(m_from, &nth, &no_arcs, FALSE); // Not incoming @@ -1121,7 +1121,7 @@ void wxLineShape::FindLineEndPoints(double *fromX, double *fromY, double *toX, d (double)second_point->x, (double)second_point->y, &end_x, &end_y); - if (m_to->GetAttachmentMode()) + if (m_to->GetAttachmentMode() != ATTACHMENT_MODE_NONE) { int nth, no_arcs; FindNth(m_to, &nth, &no_arcs, TRUE); // Incoming @@ -1139,7 +1139,7 @@ void wxLineShape::FindLineEndPoints(double *fromX, double *fromY, double *toX, d double toX = m_to->GetX(); double toY = m_to->GetY(); - if (m_from->GetAttachmentMode()) + if (m_from->GetAttachmentMode() != ATTACHMENT_MODE_NONE) { int nth, no_arcs; FindNth(m_from, &nth, &no_arcs, FALSE); @@ -1148,7 +1148,7 @@ void wxLineShape::FindLineEndPoints(double *fromX, double *fromY, double *toX, d fromY = end_y; } - if (m_to->GetAttachmentMode()) + if (m_to->GetAttachmentMode() != ATTACHMENT_MODE_NONE) { int nth, no_arcs; FindNth(m_to, &nth, &no_arcs, TRUE); @@ -1157,12 +1157,12 @@ void wxLineShape::FindLineEndPoints(double *fromX, double *fromY, double *toX, d toY = other_end_y; } - if (!m_from->GetAttachmentMode()) + if (m_from->GetAttachmentMode() == ATTACHMENT_MODE_NONE) (void) m_from->GetPerimeterPoint(m_from->GetX(), m_from->GetY(), toX, toY, &end_x, &end_y); - if (!m_to->GetAttachmentMode()) + if (m_to->GetAttachmentMode() == ATTACHMENT_MODE_NONE) (void) m_to->GetPerimeterPoint(m_to->GetX(), m_to->GetY(), fromX, fromY, &other_end_x, &other_end_y); diff --git a/utils/ogl/src/lines.h b/utils/ogl/src/lines.h index 4db39e412f..9619bf75cf 100644 --- a/utils/ogl/src/lines.h +++ b/utils/ogl/src/lines.h @@ -276,15 +276,11 @@ protected: // probably be the same) wxList* m_lineControlPoints; - double m_arrowSpacing; // Separation between adjacent arrows + double m_arrowSpacing; // Separation between adjacent arrows wxShape* m_to; wxShape* m_from; -/* - double m_actualTextWidth; // Space the text takes up - double m_actualTextHeight; // (depends on text content unlike nodes) -*/ int m_attachmentTo; // Attachment point at one end int m_attachmentFrom; // Attachment point at other end diff --git a/utils/ogl/src/makefile.nt b/utils/ogl/src/makefile.nt index d3f9dd50f1..b1b59caa7e 100644 --- a/utils/ogl/src/makefile.nt +++ b/utils/ogl/src/makefile.nt @@ -25,8 +25,8 @@ LOCALDOCDIR=$(WXDIR)\utils\ogl\docs PROGRAM=test -OBJECTS = basic.obj basic2.obj canvas.obj ogldiag.obj lines.obj misc.obj divided.obj constrnt.obj\ - composit.obj drawn.obj bmpshape.obj mfutils.obj +OBJECTS = $(THISDIR)\basic.obj $(THISDIR)\basic2.obj $(THISDIR)\canvas.obj $(THISDIR)\ogldiag.obj $(THISDIR)\lines.obj $(THISDIR)\misc.obj $(THISDIR)\divided.obj $(THISDIR)\constrnt.obj\ + $(THISDIR)\composit.obj $(THISDIR)\drawn.obj $(THISDIR)\bmpshape.obj $(THISDIR)\mfutils.obj LIBTARGET=$(WXDIR)\lib\ogl.lib @@ -59,57 +59,57 @@ basic.obj: basic.$(SRCSUFF) basic.h lines.h misc.h canvas.h $(CPPFLAGS) /Od /c /Tp $*.$(SRCSUFF) << -basic2.obj: basic2.$(SRCSUFF) basic.h lines.h misc.h canvas.h +$(THISDIR)\basic2.obj: basic2.$(SRCSUFF) basic.h lines.h misc.h canvas.h cl @<< $(CPPFLAGS) /Od /c /Tp $*.$(SRCSUFF) << -canvas.obj: canvas.$(SRCSUFF) basic.h misc.h canvas.h +$(THISDIR)\canvas.obj: canvas.$(SRCSUFF) basic.h misc.h canvas.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -ogldiag.obj: ogldiag.$(SRCSUFF) ogldiag.h canvas.h basic.h +$(THISDIR)\ogldiag.obj: ogldiag.$(SRCSUFF) ogldiag.h canvas.h basic.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -lines.obj: lines.$(SRCSUFF) basic.h misc.h canvas.h lines.h basicp.h linesp.h +$(THISDIR)\lines.obj: lines.$(SRCSUFF) basic.h misc.h canvas.h lines.h basicp.h linesp.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -misc.obj: misc.$(SRCSUFF) basic.h misc.h constrnt.h basicp.h +$(THISDIR)\misc.obj: misc.$(SRCSUFF) basic.h misc.h constrnt.h basicp.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -divided.obj: divided.$(SRCSUFF) basic.h misc.h canvas.h divided.h basicp.h +$(THISDIR)\divided.obj: divided.$(SRCSUFF) basic.h misc.h canvas.h divided.h basicp.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -constrnt.obj: constrnt.$(SRCSUFF) basic.h constrnt.h +$(THISDIR)\constrnt.obj: constrnt.$(SRCSUFF) basic.h constrnt.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -composit.obj: composit.$(SRCSUFF) basic.h misc.h canvas.h constrnt.h composit.h basicp.h +$(THISDIR)\composit.obj: composit.$(SRCSUFF) basic.h misc.h canvas.h constrnt.h composit.h basicp.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -drawn.obj: drawn.$(SRCSUFF) basic.h misc.h canvas.h drawn.h drawnp.h basicp.h +$(THISDIR)\drawn.obj: drawn.$(SRCSUFF) basic.h misc.h canvas.h drawn.h drawnp.h basicp.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -bmpshape.obj: bmpshape.$(SRCSUFF) basic.h misc.h canvas.h bmpshape.h +$(THISDIR)\bmpshape.obj: bmpshape.$(SRCSUFF) basic.h misc.h canvas.h bmpshape.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << -mfutils.obj: mfutils.$(SRCSUFF) mfutils.h +$(THISDIR)\mfutils.obj: mfutils.$(SRCSUFF) mfutils.h cl @<< $(CPPFLAGS) /c /Tp $*.$(SRCSUFF) << diff --git a/utils/ogl/src/ogldiag.cpp b/utils/ogl/src/ogldiag.cpp index d6c3f3672e..8ca66e30e8 100644 --- a/utils/ogl/src/ogldiag.cpp +++ b/utils/ogl/src/ogldiag.cpp @@ -592,3 +592,163 @@ wxShape* wxDiagram::FindShape(long id) const return NULL; } + +//// Crossings classes + +wxLineCrossings::wxLineCrossings() +{ +} + +wxLineCrossings::~wxLineCrossings() +{ + ClearCrossings(); +} + +void wxLineCrossings::FindCrossings(wxDiagram& diagram) +{ + ClearCrossings(); + wxNode* node1 = diagram.GetShapeList()->First(); + while (node1) + { + wxShape* shape1 = (wxShape*) node1->Data(); + if (shape1->IsKindOf(CLASSINFO(wxLineShape))) + { + wxLineShape* lineShape1 = (wxLineShape*) shape1; + // Iterate through the segments + wxList* pts1 = lineShape1->GetLineControlPoints(); + int i; + for (i = 0; i < (pts1->Number() - 1); i++) + { + wxRealPoint* pt1_a = (wxRealPoint*) (pts1->Nth(i)->Data()); + wxRealPoint* pt1_b = (wxRealPoint*) (pts1->Nth(i+1)->Data()); + + // Now we iterate through the segments again + + wxNode* node2 = diagram.GetShapeList()->First(); + while (node2) + { + wxShape* shape2 = (wxShape*) node2->Data(); + + // Assume that the same line doesn't cross itself + if (shape2->IsKindOf(CLASSINFO(wxLineShape)) && (shape1 != shape2)) + { + wxLineShape* lineShape2 = (wxLineShape*) shape2; + // Iterate through the segments + wxList* pts2 = lineShape2->GetLineControlPoints(); + int j; + for (j = 0; j < (pts2->Number() - 1); j++) + { + wxRealPoint* pt2_a = (wxRealPoint*) (pts2->Nth(j)->Data()); + wxRealPoint* pt2_b = (wxRealPoint*) (pts2->Nth(j+1)->Data()); + + // Now let's see if these two segments cross. + double ratio1, ratio2; + oglCheckLineIntersection(pt1_a->x, pt1_a->y, pt1_b->x, pt1_b->y, + pt2_a->x, pt2_a->y, pt2_b->x, pt2_b->y, + & ratio1, & ratio2); + + if ((ratio1 < 1.0) && (ratio1 > -1.0)) + { + // Intersection! + wxLineCrossing* crossing = new wxLineCrossing; + crossing->m_intersect.x = (pt1_a->x + (pt1_b->x - pt1_a->x)*ratio1); + crossing->m_intersect.y = (pt1_a->y + (pt1_b->y - pt1_a->y)*ratio1); + + crossing->m_pt1 = * pt1_a; + crossing->m_pt2 = * pt1_b; + crossing->m_pt3 = * pt2_a; + crossing->m_pt4 = * pt2_b; + + crossing->m_lineShape1 = lineShape1; + crossing->m_lineShape2 = lineShape2; + + m_crossings.Append(crossing); + } + } + } + node2 = node2->Next(); + } + } + } + + node1 = node1->Next(); + } +} + +void wxLineCrossings::DrawCrossings(wxDiagram& diagram, wxDC& dc) +{ + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + long arcWidth = 8; + + wxNode* node = m_crossings.First(); + while (node) + { + wxLineCrossing* crossing = (wxLineCrossing*) node->Data(); +// dc.DrawEllipse((long) (crossing->m_intersect.x - (arcWidth/2.0) + 0.5), (long) (crossing->m_intersect.y - (arcWidth/2.0) + 0.5), +// arcWidth, arcWidth); + + + // Let's do some geometry to find the points on either end of the arc. +/* + +(x1, y1) + |\ + | \ + | \ + | \ + | \ + | |\ c c1 + | a | \ + | \ + | - x <-- centre of arc + a1 | b |\ + | | \ c2 + | a2 | \ + | - \ + | b2 \ + | \ + |_______________\ (x2, y2) + b1 + +*/ + + double a1 = wxMax(crossing->m_pt1.y, crossing->m_pt2.y) - wxMin(crossing->m_pt1.y, crossing->m_pt2.y) ; + double b1 = wxMax(crossing->m_pt1.x, crossing->m_pt2.x) - wxMin(crossing->m_pt1.x, crossing->m_pt2.x) ; + double c1 = sqrt( (a1*a1) + (b1*b1) ); + + double c = arcWidth / 2.0; + double a = c * a1/c1 ; + double b = c * b1/c1 ; + + // I'm not sure this is right, since we don't know which direction we should be going in - need + // to know which way the line slopes and choose the sign appropriately. + double arcX1 = crossing->m_intersect.x - b; + double arcY1 = crossing->m_intersect.y - a; + + double arcX2 = crossing->m_intersect.x + b; + double arcY2 = crossing->m_intersect.y + a; + + dc.SetPen(*wxBLACK_PEN); + dc.DrawArc( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2, + (long) crossing->m_intersect.x, (long) crossing->m_intersect.y); + + dc.SetPen(*wxWHITE_PEN); + dc.DrawLine( (long) arcX1, (long) arcY1, (long) arcX2, (long) arcY2 ); + + node = node->Next(); + } +} + +void wxLineCrossings::ClearCrossings() +{ + wxNode* node = m_crossings.First(); + while (node) + { + wxLineCrossing* crossing = (wxLineCrossing*) node->Data(); + delete crossing; + node = node->Next(); + } + m_crossings.Clear(); +} + diff --git a/utils/ogl/src/ogldiag.h b/utils/ogl/src/ogldiag.h index 485857e440..e06e1248f4 100644 --- a/utils/ogl/src/ogldiag.h +++ b/utils/ogl/src/ogldiag.h @@ -93,5 +93,32 @@ protected: wxList* m_shapeList; }; +class wxLineCrossing: public wxObject +{ +public: + wxLineCrossing() { m_lineShape1 = NULL; m_lineShape2 = NULL; } + wxRealPoint m_pt1; // First line + wxRealPoint m_pt2; + wxRealPoint m_pt3; // Second line + wxRealPoint m_pt4; + wxRealPoint m_intersect; + wxLineShape* m_lineShape1; + wxLineShape* m_lineShape2; +}; + +class wxLineCrossings: public wxObject +{ +public: + wxLineCrossings(); + ~wxLineCrossings(); + + void FindCrossings(wxDiagram& diagram); + void DrawCrossings(wxDiagram& diagram, wxDC& dc); + void ClearCrossings(); + +public: + wxList m_crossings; +}; + #endif // _OGL_OGLDIAG_H_ diff --git a/utils/wxprop/src/proplist.cpp b/utils/wxprop/src/proplist.cpp index 0f6248f12d..6087120744 100644 --- a/utils/wxprop/src/proplist.cpp +++ b/utils/wxprop/src/proplist.cpp @@ -1750,28 +1750,72 @@ bool wxPropertyStringListEditorDialog::dialogCancelled = FALSE; // Edit the string list. bool wxListOfStringsListValidator::EditStringList(wxWindow *parent, wxStringList *stringList, const char *title) { + int largeButtonWidth = 60; + int largeButtonHeight = 25; + wxBeginBusyCursor(); wxPropertyStringListEditorDialog *dialog = new wxPropertyStringListEditorDialog(parent, title, wxPoint(10, 10), wxSize(400, 400), wxDEFAULT_DIALOG_STYLE|wxDIALOG_MODAL); dialog->stringList = stringList; - wxButton *okButton = new wxButton(dialog, wxID_OK, "OK", wxPoint(5, 5)); - wxButton *cancelButton = new wxButton(dialog, wxID_CANCEL, "Cancel", wxPoint(40, 5)); - -// wxButton *helpButton = new wxButton(dialog, (wxFunction)StringListEditorHelpProc, "Help"); -// helpButton->SetClientData((char *)this); - dialog->listBox = new wxListBox(dialog, wxID_PROP_SL_STRINGS, - wxPoint(5, 30), wxSize(300, 200), 0, NULL, wxLB_SINGLE); + wxPoint(-1, -1), wxSize(-1, -1), 0, NULL, wxLB_SINGLE); dialog->stringText = new wxPropertyStringListEditorText(dialog, wxID_PROP_SL_TEXT, "", wxPoint(5, 240), wxSize(300, -1), wxPROCESS_ENTER); dialog->stringText->Enable(FALSE); - wxButton *addButton = new wxButton(dialog, wxID_PROP_SL_ADD, "Add", wxPoint(5, 280)); - wxButton *deleteButton = new wxButton(dialog, wxID_PROP_SL_DELETE, "Delete", wxPoint(40, 280)); + wxButton *addButton = new wxButton(dialog, wxID_PROP_SL_ADD, "Add", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight)); + wxButton *deleteButton = new wxButton(dialog, wxID_PROP_SL_DELETE, "Delete", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight)); + wxButton *cancelButton = new wxButton(dialog, wxID_CANCEL, "Cancel", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight)); + wxButton *okButton = new wxButton(dialog, wxID_OK, "OK", wxPoint(-1, -1), wxSize(largeButtonWidth, largeButtonHeight)); + + okButton->SetDefault(); + + wxLayoutConstraints *c = new wxLayoutConstraints; + + c->top.SameAs (dialog, wxTop, 2); + c->left.SameAs (dialog, wxLeft, 2); + c->right.SameAs (dialog, wxRight, 2); + c->bottom.SameAs (dialog->stringText, wxTop, 2); + dialog->listBox->SetConstraints(c); + + c = new wxLayoutConstraints; + c->left.SameAs (dialog, wxLeft, 2); + c->right.SameAs (dialog, wxRight, 2); + c->bottom.SameAs (addButton, wxTop, 2); + c->height.AsIs(); + dialog->stringText->SetConstraints(c); + + c = new wxLayoutConstraints; + c->bottom.SameAs (dialog, wxBottom, 2); + c->left.SameAs (dialog, wxLeft, 2); + c->width.AsIs(); + c->height.AsIs(); + addButton->SetConstraints(c); + + c = new wxLayoutConstraints; + c->bottom.SameAs (dialog, wxBottom, 2); + c->left.SameAs (addButton, wxRight, 2); + c->width.AsIs(); + c->height.AsIs(); + deleteButton->SetConstraints(c); + + c = new wxLayoutConstraints; + c->bottom.SameAs (dialog, wxBottom, 2); + c->right.SameAs (dialog, wxRight, 2); + c->width.AsIs(); + c->height.AsIs(); + cancelButton->SetConstraints(c); + + c = new wxLayoutConstraints; + c->bottom.SameAs (dialog, wxBottom, 2); + c->right.SameAs (cancelButton, wxLeft, 2); + c->width.AsIs(); + c->height.AsIs(); + okButton->SetConstraints(c); wxNode *node = stringList->First(); while (node) @@ -1783,6 +1827,7 @@ bool wxListOfStringsListValidator::EditStringList(wxWindow *parent, wxStringList } dialog->SetClientSize(310, 305); + dialog->Layout(); dialog->Centre(wxBOTH); wxEndBusyCursor(); -- 2.45.2