typedef void* WXGC;
typedef void* WXRegion;
typedef void* WXFont;
+typedef void* WXImage;
+typedef void* WXCursor;
+typedef void* WXFontList;
#endif
#endif
// Standard cursors
typedef enum {
+ wxCURSOR_NONE = 0,
wxCURSOR_ARROW = 1,
wxCURSOR_BULLSEYE,
wxCURSOR_CHAR,
wxCURSOR_BASED_ARROW_UP,
wxCURSOR_BASED_ARROW_DOWN
#endif
-} _standard_cursors_t;
+} wxStockCursor;
class WXDLLEXPORT wxSize
{
bool Create(const wxBitmap& bitmap);
inline WXPixmap GetPixmap() const { return m_pixmap; }
+ inline void SetPixmap(WXPixmap pixmap) { m_pixmap = pixmap; }
protected:
WXPixmap m_pixmap;
~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)
{ 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);
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); }
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_
DECLARE_DYNAMIC_CLASS(wxChoice)
public:
- inline wxChoice() { m_noStrings = 0; }
+ wxChoice();
+ ~wxChoice();
inline wxChoice(wxWindow *parent, wxWindowID id,
const wxPoint& pos = wxDefaultPosition,
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
#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;
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)
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);
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;
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)
// 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();
#include "wx/bitmap.h"
+/*
+// Same as for wxBitmap
class WXDLLEXPORT wxIconRefData: public wxBitmapRefData
{
friend class WXDLLEXPORT wxBitmap;
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
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();
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_
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);
}
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
#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;
~wxPaletteRefData();
protected:
- WXColormap m_colormap;
+ wxList m_palettes;
};
#define M_PALETTEDATA ((wxPaletteRefData *)m_refData)
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
typedef unsigned int size_t;
-#if !USE_OWNER_DRAWN
+#if !wxUSE_OWNER_DRAWN
#error "wxCheckListBox class requires owner-drawn functionality."
#endif
#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
#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
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)
{
wxObject *obj = (wxObject *)m_actualData;
wxClassInfo *info = obj->GetClassInfo();
-
+/*
if (info && info->GetClassName())
wxTrace("%s", info->GetClassName());
else
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());
}
}
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());
}
}
// 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);
}
# 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
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'
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);
#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)
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;
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);
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)
{
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;
}
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).
* 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()
{
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;
}
+
// 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,
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
if (sel > -1)
return wxString(this->GetString (sel));
else
- return wxString("");
+ return wxEmptyString;
}
bool wxChoice::SetStringSelection (const wxString& s)
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);
+ }
+ }
+}
+
#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)
}
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)
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;
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;
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;
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);
#include "wx/filedlg.h"
#include "wx/intl.h"
+#include <Xm/Xm.h>
+
#if !USE_SHARED_LIBRARY
IMPLEMENT_CLASS(wxFileDialog, wxDialog)
#endif
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)
#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;
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;
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()
// 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,
}
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;
#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)
* 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,
{
UnRef();
- m_refData = new wxIconRefData;
+ m_refData = new wxBitmapRefData;
wxBitmapHandler *handler = FindHandler(type);
#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,
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()
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) ;
+}
+
+
// 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
/*
*
*/
+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()
{
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;
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);
+}
/////////////////////////////////////////////////////////////////////////////
// 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
/////////////////////////////////////////////////////////////////////////////
#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)
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
*/
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);
}
/*!
}
// 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
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;
}
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
case wxRGN_DIFF:
// TODO
break ;
- case wxRGN_COPY:
+ case wxRGN_COPY: // Don't have to do this one
default:
// TODO
break ;
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;
}
// Is region empty?
bool wxRegion::Empty() const
{
- // TODO
- return FALSE;
+ return m_refData ? XEmptyRegion(M_REGION) : FALSE;
}
//-----------------------------------------------------------------------------
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)?
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
// 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
{
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)
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
/////// 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
*/
-#if USE_SPLINES
+#if wxUSE_SPLINES
////#define wx_round(a) (int)((a)+.5)
//#define wx_round(a) (a)
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
}
-#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;
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)
}
-#endif // USE_POSTSCRIPT
+#endif // wxUSE_POSTSCRIPT
-#endif // USE_SPLINES
+#endif // wxUSE_SPLINES
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
}
// Cursors by stock number
wxCursor::wxCursor(int cursor_type)
{
- m_refData = new wxIconRefData;
+ m_refData = new wxCursorRefData;
/* TODO
switch (cursor_type)
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)
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;
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)
int nearest_attachment = 0;
-
// If within the bounding box, check the attachment points
// within the object.
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)));
// 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:
bool wxShape::MoveLineToNewAttachment(wxDC& dc, wxLineShape *to_move,
double x, double y)
{
- if (!GetAttachmentMode())
+ if (GetAttachmentMode() == ATTACHMENT_MODE_NONE)
return FALSE;
int newAttachment, oldAttachment;
GetEventHandler()->OnDraw(dc);
GetEventHandler()->OnDrawContents(dc);
GetEventHandler()->OnDrawControlPoints(dc);
+ GetEventHandler()->OnDrawBranches(dc);
}
}
{
GetEventHandler()->OnErase(dc);
GetEventHandler()->OnEraseControlPoints(dc);
+ GetEventHandler()->OnDrawBranches(dc, TRUE);
}
void wxShape::EraseContents(wxDC& dc)
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)
{
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);
int iVal = (int) m_attachmentMode;
clause->GetAttributeValue("use_attachments", iVal);
- m_attachmentMode = (iVal != 0);
+ m_attachmentMode = iVal;
clause->GetAttributeValue("sensitivity", m_sensitivity);
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);
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();
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)
{
bool isEnd = (line && line->IsEnd(this));
+ int physicalAttachment = LogicalToPhysicalAttachment(attachment);
+
// Simplified code
- switch (attachment)
+ switch (physicalAttachment)
{
case 0:
{
}
default:
{
- return wxShape::GetAttachmentPosition(attachment, x, y, nth, no_arcs, line);
+ return FALSE;
break;
}
}
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;
+ }
+}
+
#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;
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);
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; }
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,
// 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.)
// 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();
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;
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
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)));
// 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...
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;
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)
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:
{
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);
}
double x2, double y2,
double *x3, double *y3,
double xOffset, double yOffset,
- bool attachmentMode)
+ int attachmentMode)
{
int n = m_noPoints;
// 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...
double x2, double y2,
double *x3, double *y3,
double xOffset, double yOffset,
- bool attachmentMode)
+ int attachmentMode)
{ return FALSE; }
protected:
double x2, double y2,
double *x3, double *y3,
double xOffset, double yOffset,
- bool attachmentMode);
+ int attachmentMode);
public:
wxRealPoint* m_points;
// 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)
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
(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
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);
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);
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);
// 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
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
$(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)
<<
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();
+}
+
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_
// 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)
}
dialog->SetClientSize(310, 305);
+ dialog->Layout();
dialog->Centre(wxBOTH);
wxEndBusyCursor();