]> git.saurik.com Git - wxWidgets.git/commitdiff
More wxMotif work, OGL enhancements, USE_ macro corrections, object.cpp delete
authorJulian Smart <julian@anthemion.co.uk>
Mon, 28 Sep 1998 15:42:54 +0000 (15:42 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Mon, 28 Sep 1998 15:42:54 +0000 (15:42 +0000)
operator correction for VC++ 6

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@780 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

44 files changed:
include/wx/defs.h
include/wx/gdicmn.h
include/wx/motif/bitmap.h
include/wx/motif/choice.h
include/wx/motif/cursor.h
include/wx/motif/font.h
include/wx/motif/icon.h
include/wx/motif/listbox.h
include/wx/motif/palette.h
include/wx/msw/checklst.h
include/wx/msw/ole/dropsrc.h
include/wx/msw/ole/droptgt.h
src/common/docview.cpp
src/common/memory.cpp
src/common/object.cpp
src/make.env
src/motif/app.cpp
src/motif/bitmap.cpp
src/motif/choice.cpp
src/motif/cursor.cpp
src/motif/dcclient.cpp
src/motif/filedlg.cpp
src/motif/font.cpp
src/motif/icon.cpp
src/motif/listbox.cpp
src/motif/palette.cpp
src/motif/region.cpp
src/motif/window.cpp
src/msw/makefile.nt
src/msw/tbarmsw.cpp
src/msw/xfspline.inc
src/stubs/cursor.cpp
utils/ogl/src/basic.cpp
utils/ogl/src/basic.h
utils/ogl/src/basic2.cpp
utils/ogl/src/divided.cpp
utils/ogl/src/drawn.cpp
utils/ogl/src/drawnp.h
utils/ogl/src/lines.cpp
utils/ogl/src/lines.h
utils/ogl/src/makefile.nt
utils/ogl/src/ogldiag.cpp
utils/ogl/src/ogldiag.h
utils/wxprop/src/proplist.cpp

index 13c94ff050bac1bbd81270eda7796336e73be513..888a5b0cc6c247fe37cc5c405db886e5f3d6981c 100644 (file)
@@ -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
index d726d44c1eb22ecefeb824272394cd4e1fe4791e..49cbec544808b40c919201e07325c03767311973 100644 (file)
@@ -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
 {
index 4fec4f62c1342e60ee09506bdd695c88b3fb9d7d..9c60d94c9117df0dbd98fa319f7d1710de957566 100644 (file)
@@ -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_
index 7db33d7ad4d9b5d2d648103e87c1473c5de0c5ae..30423c0e96138c66a3f75de321605f6b065cb3b2 100644 (file)
@@ -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
index 3db0a16fe7d70ed29c10c2b44a0e6de4a44ed74d..0fde1803354b01c56ab07e190532d946998a028e 100644 (file)
 
 #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);
index b5149ef4dc93e37da04219964237bb1288855ee2..769b4d6352d2f0e4122c7f2ab904a5fe2f34366f 100644 (file)
 
 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();
index 012fd0754d45b23e3d7814e5cb44298ee2155909..92eb0eccfc257484d9cbd28fe38c93dc25a02ce8 100644 (file)
@@ -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_
index 5ba7762189e96658d8be2c8ef141cbd68a8a5af1..5ca22a7d032382f36f944e8b58ed0e2b6ede77be 100644 (file)
@@ -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
index 4bc644cb7fc5b0323dd62e38ce290c42cf5ad2dc..589b7735e03dd1eb2811d70b39752a3d69d61b21 100644 (file)
 #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
index 163291f121c51e55c200e5711eeef2aa41f504da..a58714daa6e2484166c8a11e8a4ef15e06e180bb 100644 (file)
@@ -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
 
index 4ed544cf38e4c7426a581d03f75453a4c24d469c..a36324a994e6247929e64583e46d3fabedaa4801 100644 (file)
@@ -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
 
index 065d56c63f0eeef86b7e92266ab8c2c8cd73be11..95484cf7a68fcc25424f2ff521b7ccf33c2ce753 100644 (file)
@@ -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
 
index 81ec15a123d74a56b535686113f17c473b31d7a9..2ab0f4cd24503c7ea0344a52205b6d84f466d6c2 100644 (file)
@@ -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)
index 304e9ce1ec168dffbf8eac15e3fab68e5f082dcb..d3771ff98c2de795ace8fb835a40a5c3129926f5 100644 (file)
@@ -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());
   }
 }
index d5afed37dee3b6c784ac350c1cb6c3c3c6092019..d26826ebe253cafe90d60334d53445afacf1b774 100644 (file)
@@ -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);
 }
index a5a1a2d4a1f30ec30ce79885248c32d14129ae42..874f37ec13a695463aed68925cec251f1e0bf91a 100644 (file)
@@ -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'
 
index d8df53ed4c0c2b359abc9f2d45284efe38b5c573..df82c80919f1de7fa92a42fd97389a5b4bebcb43 100644 (file)
@@ -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);
 
index 865b319997a2c4091c6862a8d70fa7abd83105b8..58b53da7f799aed0f8c775691b02fe802ca4c486 100644 (file)
 #include "wx/icon.h"
 #include "wx/log.h"
 
+#include <Xm/Xm.h>
+
+#include "wx/motif/private.h"
+
+// TODO: correct symbol, path?
+#if USE_XPM
+#include <X11/xpm.h>
+#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;
 }
+
index 9ba26a3a032f80eb9a4cf7623348f5124f43de46..7012c75c0fea4216716001017388e535baa27815 100644 (file)
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/choice.h"
+#include "wx/utils.h"
+
+#include <Xm/Xm.h>
+#include <Xm/PushBG.h>
+#include <Xm/PushB.h>
+#include <Xm/RowColumn.h>
+
+#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);
+        }
+    }
+}
+
index 4ecd0ad6d557fa7ecbe8757fa76ea4f381427d29..24c94be559871dd43c2d9bc53262307d50e05ffd 100644 (file)
 #endif
 
 #include "wx/cursor.h"
+#include "wx/gdicmn.h"
 #include "wx/icon.h"
+#include "wx/app.h"
+#include "wx/utils.h"
+
+#include <Xm/Xm.h>
+#include <X11/cursorfont.h>
+
+#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)
 }
 
 
index 9f994b2747c0852f259e8c410617b53ebd9c0466..ebe87a10d51277a1dfbc10d453f4291e20b0af19 100644 (file)
@@ -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);
index fdd54ea7b21ff4833996109544f0d997d29c2bb4..04966afc992f5dbbe859b500b273a7bdef143d26 100644 (file)
@@ -19,6 +19,8 @@
 #include "wx/filedlg.h"
 #include "wx/intl.h"
 
+#include <Xm/Xm.h>
+
 #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)
index ae4ccd07ffe8c6beae3fe89eb18bfd3e09d75260..c03570a342460e2bdfe6bec716bc75ad4f561420 100644 (file)
 #include "wx/gdicmn.h"
 #include "wx/utils.h"
 
-#include <X11/Xlib.h>
+#include <Xm/Xm.h>
 
 #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;
index 834c9ff1ccfc71fa7fbfbac861f13cb89fd086eb..0f3ff04a6409a5726ce0a3ffa4aa7ec7e244d4a8 100644 (file)
 #endif
 
 #include "wx/icon.h"
+#include "wx/window.h"
+
+#include <Xm/Xm.h>
+#include <X11/cursorfont.h>
+
+#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);
 
index 9352c32bc209ad7f7ed1e0d912d63daffd99964c..2dffe82cb1e56a4eaeecf77b82d5891a7b6137da 100644 (file)
 #include "wx/settings.h"
 #include "wx/dynarray.h"
 #include "wx/log.h"
+#include "wx/utils.h"
+
+#include <Xm/List.h>
+#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; i<n; i++)
+  {
+    XmString text = XmStringCreateSimple(choices[i]);
+    XmListAddItemUnselected(listBox, text, 0);
+    XmStringFree(text);
+  }
+***/
+  XmString *text = new XmString[n];
+  int i;
+  for (i = 0; i < n; i++)
+    text[i] = XmStringCreateSimple ((char*) (const char*) choices[i]);
+
+  if ( clientData )
+    for (i = 0; i < n; i++)
+      m_clientDataList.Append ((long) i, (wxObject *) clientData[i]);
+
+  XmListAddItems (listBox, text, n, 0);
+  for (i = 0; i < n; 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);
 
-  // TODO
+  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);
+
+  m_noItems = n;
 }
 
 int wxListBox::FindString(const wxString& s) const
 {
-    // TODO
+  XmString str = XmStringCreateSimple ((char*) (const char*) s);
+  int *positions = NULL;
+  int no_positions = 0;
+  bool success = XmListGetMatchPos ((Widget) m_mainWidget, str, &positions, &no_positions);
+  XmStringFree (str);
+  if (success)
+    {
+      int pos = positions[0];
+      if (positions)
+    XtFree ((char *) positions);
+      return pos - 1;
+    }
+  else
     return -1;
 }
 
 void wxListBox::Clear()
 {
+  if (m_noItems <= 0)
+    return;
+
+  int width1, height1;
+  int width2, height2;
+
+  Widget listBox = (Widget) m_mainWidget;
+  GetSize (&width1, &height1);
+
+  XmListDeleteAllItems (listBox);
+  m_clientDataList.Clear ();
+  GetSize (&width2, &height2);
+
+  // Correct for randomly resized listbox - bad boy, Motif!
+  if (width1 != width2 || height1 != height2)
+    SetSize (-1, -1, width1, height1);
+
   m_noItems = 0;
-  // TODO
 }
 
 void wxListBox::SetSelection(int N, bool select)
 {
-    // TODO
+  m_inSetValue = TRUE;
+  if (select)
+    {
+/*
+      if (m_windowStyle & wxLB_MULTIPLE)
+    {
+      int *selections = NULL;
+      int n = GetSelections (&selections);
+
+      // This hack is supposed to work, to make it possible to select more
+      // than one item, but it DOESN'T under Motif 1.1.
+
+      XtVaSetValues ((Widget) m_mainWidget, XmNselectionPolicy, XmMULTIPLE_SELECT, NULL);
+
+      int i;
+      for (i = 0; i < n; i++)
+        XmListSelectPos ((Widget) m_mainWidget, selections[i] + 1, FALSE);
+
+      XmListSelectPos ((Widget) m_mainWidget, N + 1, FALSE);
+
+      XtVaSetValues ((Widget) m_mainWidget, XmNselectionPolicy, XmEXTENDED_SELECT, NULL);
+    }
+      else
+*/
+    XmListSelectPos ((Widget) m_mainWidget, N + 1, FALSE);
+
+    }
+  else
+    XmListDeselectPos ((Widget) m_mainWidget, N + 1);
+
+  m_inSetValue = FALSE;
 }
 
 bool wxListBox::Selected(int N) const
 {
-    // TODO
+  // In Motif, no simple way to determine if the item is selected.
+  wxArrayInt theSelections;
+  int count = GetSelections (theSelections);
+  if (count == 0)
     return FALSE;
+  else
+  {
+    int j;
+    for (j = 0; j < count; j++)
+      if (theSelections[j] == N)
+    return TRUE;
+  }
+  return FALSE;
 }
 
 void wxListBox::Deselect(int N)
 {
-    // TODO
+    XmListDeselectPos ((Widget) m_mainWidget, N + 1);
 }
 
 char *wxListBox::GetClientData(int N) const
 {
-    // TODO
-    return (char *)NULL;
+    wxNode *node = m_clientDataList.Find ((long) N);
+    if (node)
+        return (char *) node->Data ();
+    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) ;
+}
+
+
index e5ec7326731715b17f2f745b1b13bb8ec1954341..58262fb1bef2807637b7225d01db41dc6f7cc471 100644 (file)
@@ -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 <u7y22ab@sunmail.lrz-muenchen.de>
+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 <Xm/Xm.h>
+#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<pix_array_n; i=j) {
+        while(j<pix_array_n && pix_array[j]!=0) j++;
+        if(j > i) XFreeColors(display, cmap, &pix_array[i], j-i, 0);
+        while(j<pix_array_n && pix_array[j]==0) j++;
+      }
+      delete [] pix_array;
+    }
+
+    if (destroyable)
+      XFreeColormap(display, cmap);
+
+    next = node->Next();
+    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);
+}
 
index fcc58d31755e1dd562b684b7b7c4d226cdc1faed..3a8f5603d0a91936fa171a0b9687eeeeb9ee77a8 100644 (file)
@@ -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 <Xm/Xm.h>
+// #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
index 17a54f842d6d56a5617bb2f80c3063449a63e00b..c3a6018292e95b0c0a5d5caf33244a2813a43775 100644 (file)
@@ -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)
index ba06ea9590d4b1b58584181b146dc616a72c435a..c35b1ecb063b106f2b59f56854c28e61cb964767 100644 (file)
@@ -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
 
index 84bf089014a59c8de3e4231a8cc184cb7ab3b0b5..91bed87c4b7360e1afe63989ac735f67f69e4cd9 100644 (file)
@@ -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
 
index 792cf3e23fe76b069fdabf16fd7772ba72cb1440..6e98adb455d09bbe8be012f2e00020da833d55e3 100644 (file)
@@ -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
 
index f5cc609f7ec125ab82f4f74eea861b93db5a1872..4333364c931cc08c781cc38f2998b2fc29bc69c8 100644 (file)
@@ -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)
index 33d25bdf2196829dbc2bb170774636043ced43b8..1dff73fedc422b97a17dfc5596656a52c9f146e7 100644 (file)
@@ -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;
+    }
+}
+
index 52b78d16eda238af5b1bbf68ee85d5ecfa1ff1b0..ad8d5fb0961526e37752f477702e39b6a87dced2 100644 (file)
 
 #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
index e54c84bbebbe65fe7f98b3105b26d73d9f55d3af..40b86bf5f37ce585b455a64d1af761d27814aa37 100644 (file)
@@ -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:
       {
index 73fbe834345d95003f0b9639ac107fab6ec6f0f7..9768075e72e73445eaa21da378d85e493e3f638f 100644 (file)
@@ -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);
   }
index f6d8f33a98d1c0d630ab72266bc81d87753e4c13..498448efab3cb416550844e0ff055db7afd3654c 100644 (file)
@@ -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...
index ab5ef12631efd04914e90f6ec6e95e0c9c30efa8..991f5dc8236aa873cbc496cc4254bc1b59d6f92e 100644 (file)
@@ -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;
index 56508e4c43d16d7abaf3339f0ef1c5be91e05e3d..d03b2f401a8ed2bce3b272411d518e1fbd086988 100644 (file)
@@ -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);
index 4db39e412f65e12e8fb487b1ab10aae728f70fed..9619bf75cfd7ea3e5e566a388336d677f901a263 100644 (file)
@@ -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
 
index d3f9dd50f1ad779d4fecfd8317b79db54df05830..b1b59caa7ea86ec17d41041d5d865e1298bfc034 100644 (file)
@@ -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)
 <<
index d6c3f3672e618ec97f10a5b28d30deb58c388818..8ca66e30e86d132952a271373d1a4a8b55f3c615 100644 (file)
@@ -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();
+}
+
index 485857e440a30aa2a4d696ba5999b04a5679129f..e06e1248f452d7c06a76caaef8f094a967bb8a3d 100644 (file)
@@ -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_
index 0f6248f12d45926d5bf17bc620de7a1673ff8519..6087120744e653874972a110de02c18e6c5b986c 100644 (file)
@@ -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();