1. wxMenu changes: wxMenuBase appears, several new functions for dynamic menu

handling as well
2. new sample: menu
3. small corrections to wxFileHistory made possible by wxMenu changes
4. ugly fix for panel loaded from resources and TABbing
5. wxDataObject &c doc updates


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4288 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-11-02 01:25:43 +00:00
parent cf85cb95f1
commit 717a57c2fa
29 changed files with 2205 additions and 1790 deletions

View File

@@ -1,16 +1,21 @@
\section{\class{wxBitmapDataObject}}\label{wxbitmapdataobject} \section{\class{wxBitmapDataObject}}\label{wxbitmapdataobject}
wxBitmapDataObject is a specialization of wxDataObject for bitmap data. It can be wxBitmapDataObject is a specialization of wxDataObject for bitmap data. It can
used without change to paste data into the \helpref{wxClipboard}{wxclipboard} be used without change to paste data into the
or a \helpref{wxDropSource}{wxdropsource}. A user may wish to derive a new class \helpref{wxClipboard}{wxclipboard} or a \helpref{wxDropSource}{wxdropsource}. A
from this class for providing a bitmap on-demand in order to minimize memory consumption user may wish to derive a new class from this class for providing a bitmap
when offering data in several formats, such as a bitmap and GIF. on-demand in order to minimize memory consumption when offering data in several
formats, such as a bitmap and GIF.
In order to offer bitmap data on-demand \helpref{GetSize}{wxbitmapdataobjectgetsize} \wxheading{Virtual functions to override}
and \helpref{WriteData}{wxbitmapdataobjectwritedata} will have to be overridden.
This class may be used as is, but
\helpref{GetBitmap}{wxbitmapdataobjectgetbitmap} may be overridden to increase
efficiency.
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxDataObjectSimple}{wxdataobjectsimple}
\helpref{wxDataObject}{wxdataobject} \helpref{wxDataObject}{wxdataobject}
\wxheading{Include files} \wxheading{Include files}
@@ -19,64 +24,17 @@ and \helpref{WriteData}{wxbitmapdataobjectwritedata} will have to be overridden.
\wxheading{See also} \wxheading{See also}
\helpref{Clipboard and drag and drop overview}{wxclipboardonfigoverview},
\helpref{wxDataObject}{wxdataobject},
\helpref{wxDataObjectSimple}{wxdataobjectsimple},
\helpref{wxFileDataObject}{wxfiledataobject},
\helpref{wxTextDataObject}{wxtextdataobject},
\helpref{wxDataObject}{wxdataobject} \helpref{wxDataObject}{wxdataobject}
\latexignore{\rtfignore{\wxheading{Members}}} \func{}{wxBitmapDataObject}{\param{const wxBitmap\& }{bitmap = wxNullBitmap}}
\membersection{wxBitmapDataObject::wxBitmapDataObject}\label{wxbitmapdataobjectwxbitmapdataobject} Constructor, optionally passing a bitmap (otherwise use
\helpref{SetBitmap}{wxbitmapdataobjectsetbitmap} later)
\func{}{wxBitmapDataObject}{\void}
Default constructor. Call \helpref{SetBitmap}{wxbitmapdataobjectsetbitmap} later
or override \helpref{WriteData}{wxbitmapdataobjectwritedata} and
\helpref{GetSize}{wxbitmapdataobjectgetsize} for providing data on-demand.
\func{}{wxBitmapDataObject}{\param{const wxBitmap\& }{bitmap}}
Constructor, passing a bitmap.
\membersection{wxBitmapDataObject::GetSize}\label{wxbitmapdataobjectgetsize}
\constfunc{virtual size\_t}{GetSize}{\void}
Returns the data size. By default, returns the size of the bitmap data
set in the constructor or using \helpref{SetBitmap}{wxbitmapdataobjectsetbitmap}.
This can be overridden to provide size data on-demand. Note that you'd
have to call the inherited GetSize method as this is the only way
to get to know the transfer size of the bitmap in a platform dependent
way - a bitmap has different size under GTK and Windows. In practice,
this would look like this:
\begin{verbatim}
size_t MyBitmapDataObject::GetSize()
{
// Get bitmap from global container. This container
// should be able to "produce" data in all formats
// offered by the application but store it only in
// one format to reduce memory consumption.
wxBitmap my_bitmap = my_global_container->GetBitmap();
// temporarily set bitmap
SetBitmap( my_bitmap );
size_t ret = wxBitmapDataObject::GetSize();
// unset bitmap again
SetBitmap( wxNullBitmap );
retrun ret;
}
\end{verbatim}
TODO: Offer a nicer way to do this. Maybe by providing a platform
dependent function in this class like
\begin{verbatim}
size_t GetBitmapSize( const wxBitmap &bitmap )
\end{verbatim}
\membersection{wxBitmapDataObject::GetBitmap}\label{wxbitmapdataobjectgettext} \membersection{wxBitmapDataObject::GetBitmap}\label{wxbitmapdataobjectgettext}
@@ -91,26 +49,8 @@ the \helpref{wxClipboard}{wxclipboard}.
\func{virtual void}{SetBitmap}{\param{const wxBitmap\& }{bitmap}} \func{virtual void}{SetBitmap}{\param{const wxBitmap\& }{bitmap}}
Sets the bitmap associated with the data object. This method is called Sets the bitmap associated with the data object. This method is called when the
internally when retrieving data from the \helpref{wxClipboard}{wxclipboard} data object receives data. Usually there will be no reason to override this
and may be used to paste data to the clipboard directly (instead of function.
on-demand).
\membersection{wxBitmapDataObject::WriteData}\label{wxbitmapdataobjectwritedata}
\constfunc{virtual void}{WriteData}{\param{void}{*dest} }
Write the data owned by this class to {\it dest}. By default, this
calls \helpref{WriteBitmap}{wxbitmapdataobjectwritebitmap} with the bitmap
set in the constructor or using \helpref{SetBitmap}{wxbitmapdataobjectsetbitmap}.
This can be overridden to provide bitmap data on-demand; in this case
\helpref{WriteBitmap}{wxbitmapdataobjectwritebitmap} must be called from
within th overriding WriteData() method.
\membersection{wxBitmapDataObject::WriteBitmap}\label{wxbitmapdataobjectwritebitmap}
\constfunc{void}{WriteBitmap}{\param{const wxBitmap\& }{bitmap}\param{void}{*dest} }
Writes the the bitmap {\it bitmap} to {\it dest}. This method must be called
from \helpref{WriteData}{wxbitmapdataobjectwritedata}.

View File

@@ -40,6 +40,8 @@
\input cursor.tex \input cursor.tex
\input database.tex \input database.tex
\input dataobj.tex \input dataobj.tex
\input dobjcomp.tex
\input dobjsmpl.tex
\input datstrm.tex \input datstrm.tex
\input date.tex \input date.tex
\input dc.tex \input dc.tex

View File

@@ -1,38 +1,118 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: dataobj.tex
%% Purpose: wxDataObject documentation
%% Author: Vadim Zeitlin
%% Modified by:
%% Created: 18.10.99
%% RCS-ID: $Id$
%% Copyright: (c) wxWindows team
%% Licence: wxWindows licence
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{\class{wxDataObject}}\label{wxdataobject} \section{\class{wxDataObject}}\label{wxdataobject}
A wxDataObject represents data that can be copied to or from the clipboard, or A wxDataObject represents data that can be copied to or from the clipboard, or
dragged and dropped. There are two classes directly derived from wxDataObject: dragged and dropped. The important thing about wxDataObject is that this is a
wxDataObjectSimple and wxDataObjectComposite. As you will guess, wxDataObjectSimple "smart" piece of data unlike usual "dumb" data containers such as memory
holds data for a single format (such as HTML or text) and wxDataObjectComposite buffers or files. Being "smart" here means that the data object itself should
can hold any number of wxDataObjectSimple classes. Please note that this is an know what data formats it supports and how to render itself in each of
easy way to use Drag'n'Drop and the clipboard with multiple formats, but not the supported formats.
most efficient one as each wxDataObjectSimple would contain the whole data in its
respective formars. Now imagine that you want to paste 200 pages of text in your
proprietary format, as well as Word, RTF, HTML, Unicode and plain text to the
clipboard and even today's computers are in trouble. For this case, you will have
to derive from wxDataObject directly and make it enumerate its formats and provide
the data in the requested format on demand.
Note that neither the GTK data transfer mechanisms for the clipboard and Drag'n'Drop A supported format, incidentally, is exactly the format in which the data can
nor the OLE data transfer copies any data until another application actually be requested from a data object or from which the data object may be set. In
requests the data. This is in contrast to the "feel" offered to the user of a the general case, an object may support different formats on "input" and
program who would normally think that the data resides in the clipboard after "output", i.e. it may be able to render itself in a given format but not be
having pressed "Copy" - in reality it is only declared to be available. created from data on this format or vice versa. wxDataObject defines an
enumeration type
There are several predefined data object classes derived from wxDataObjectSimple: \begin{verbatim}
\helpref{wxFileDataObject}{wxfiledataobject}, \helpref{wxTextDataObject}{wxtextdataobject} enum Direction
and \helpref{wxBitmapDataObject}{wxbitmapdataobject} which can be used without change. {
Get = 0x01, // format is supported by GetDataHere()
Set = 0x02 // format is supported by SetData()
};
\end{verbatim}
You may also derive your own data object classes from \helpref{wxCustomDataObject}{wxprivatedataobject} which allows to distinguish between them. See
for user-defined types. The format of user-defined data is given as mime-type string literal, \helpref{wxDataFormat}{wxdataformat} documentation for more about formats.
such as "application/word" or "image/png". These strings are used as they are under Unix (so
far only GTK) to identify a format and are translated into their Windows equivalent under Not surprizingly, being "smart" comes at a price of added complexity. This is
Win32 (using the OLE IDataObject for data exchange to and from the clipboard and for Drag'n'Drop). reasonable for the situations when you really need to support multiple formats,
Note that the format string translation under Windows is not yet finnished. but may be annoying if you only want to do something simple like cut and paste
text.
To provide a solution for both cases, wxWindows has two predefined classes
which derive from wxDataObject:
\helpref{wxDataObjectSimple}{wxdataobjectsimple} and
\helpref{wxDataObjectComposite}{wxdataobjectcomposite}.
\helpref{wxDataObjectSimple}{wxdataobjectsimple} is
the simplest wxDataObject possible and only holds data in a single format (such
as HTML or text) and \helpref{wxDataObjectComposite}{wxdataobjectcomposite} is
the simplest way to implement wxDataObject which does support multiple formats
because it achievs this by simply holding several wxDataObjectSimple objects.
So, you have several solutions when you need a wxDataObject class (and you need
one as soon as you want to transfer data via the clipboard or drag and drop):
\begin{twocollist}
\twocolitem{0. Use one of built-in classes}{You may use wxTextDataObject,
wxBitmapDataObject or wxFileDataObject in the simplest cases when you only need
to support one format and your data is either text, bitmap or list of files}
\twocolitem{1. Derive your class from wxDataObjectSimple}{This is the simplest
solution for custom data - you will only support one format and so probably
won't be able to communicate with other programs, but data transfer will work
in your program (or between different copies of it).}
\twocolitem{2. Use wxDataObjectComposite}{This is a quite simple, but rather
powerful solution which allows you to support any number of formats (either
standard or custom if you combine it with the previous solution).}
\twocolitem{3. Derive from wxDataObject directly}{This is the solution of
maximal flexibility and efficiency, but it also is the most difficult to
implement.}
\end{twocollist}
Please note that the easiest way to use Drag'n'Drop and the clipboard with
multiple formats is by using wxDataObjectComposite, but it is not the most
efficient one as each wxDataObjectSimple would contain the whole data in its
respective formars. Now imagine that you want to paste 200 pages of text in
your proprietary format, as well as Word, RTF, HTML, Unicode and plain text to
the clipboard and even today's computers are in trouble. For this case, you
will have to derive from wxDataObject directly and make it enumerate its
formats and provide the data in the requested format on demand.
Note that neither the GTK data transfer mechanisms for the clipboard and
Drag'n'Drop nor the OLE data transfer copies any data until another application
actually requests the data. This is in contrast to the "feel" offered to the
user of a program who would normally think that the data resides in the
clipboard after having pressed "Copy" - in reality it is only declared to be
available.
There are several predefined data object classes derived from
wxDataObjectSimple: \helpref{wxFileDataObject}{wxfiledataobject},
\helpref{wxTextDataObject}{wxtextdataobject} and
\helpref{wxBitmapDataObject}{wxbitmapdataobject} which can be used without
change.
You may also derive your own data object classes from
\helpref{wxCustomDataObject}{wxprivatedataobject} for user-defined types. The
format of user-defined data is given as mime-type string literal, such as
"application/word" or "image/png". These strings are used as they are under
Unix (so far only GTK) to identify a format and are translated into their
Windows equivalent under Win32 (using the OLE IDataObject for data exchange to
and from the clipboard and for Drag'n'Drop). Note that the format string
translation under Windows is not yet finnished.
\wxheading{Virtual functions to override}
Each class derived directly from wxDataObject must override and implement all
of its functions which are pure virtual in the base class.
The data objects which only render their data or only set it (i.e. work in
only one direction), should return 0 from
\helpref{GetFormatCount}{wxdataobjectgetformatcount}.
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxObject}{wxobject} None
\wxheading{Include files} \wxheading{Include files}
@@ -40,13 +120,16 @@ Note that the format string translation under Windows is not yet finnished.
\wxheading{See also} \wxheading{See also}
\helpref{Clipboard and drag and drop overview}{wxclipboardonfigoverview},
\helpref{DnD sample}{samplednd},
\helpref{wxFileDataObject}{wxfiledataobject}, \helpref{wxFileDataObject}{wxfiledataobject},
\helpref{wxTextDataObject}{wxtextdataobject}, \helpref{wxTextDataObject}{wxtextdataobject},
\helpref{wxBitmapDataObject}{wxbitmapdataobject}, \helpref{wxBitmapDataObject}{wxbitmapdataobject},
\helpref{wxPrivateDataObject}{wxprivatedataobject}, \helpref{wxPrivateDataObject}{wxprivatedataobject},
\helpref{Drag and drop overview}{wxdndoverview}, \helpref{wxDropTarget}{wxdroptarget}, \helpref{wxDropTarget}{wxdroptarget},
\helpref{wxDropSource}{wxdropsource}, \helpref{wxDropSource}{wxdropsource},
\helpref{wxTextDropTarget}{wxtextdroptarget}, \helpref{wxFileDropTarget}{wxfiledroptarget} \helpref{wxTextDropTarget}{wxtextdroptarget},
\helpref{wxFileDropTarget}{wxfiledroptarget}
\latexignore{\rtfignore{\wxheading{Members}}} \latexignore{\rtfignore{\wxheading{Members}}}
@@ -62,17 +145,21 @@ Constructor.
Destructor. Destructor.
\membersection{wxDataObject::GetFormatCount}\label{wxdataobjectgetformatcount} \membersection{wxDataObject::GetAllFormats}\label{wxdataobjectgetallformats}
\constfunc{virtual size_t}{GetFormatCount}{\void} \constfunc{virtual void}{GetAllFormats}{
\param{wxDataFormat *}{formats},
\param{Direction}{ dir = Get}}
Return the number of available formats. Copy all supported formats in the given direction to the array pointed to by
{\it formats} (there is enough place for GetFormatCount(dir) formats in it).
\membersection{wxDataObject::GetDataHere}\label{wxdataobjectgetdatahere} \membersection{wxDataObject::GetDataHere}\label{wxdataobjectgetdatahere}
\constfunc{virtual bool}{GetDataHere}{\param{const wxDataFormat\&}{ format}, \param{void}{*buf} } \constfunc{virtual bool}{GetDataHere}{\param{const wxDataFormat\&}{ format}, \param{void }{*buf} }
The method will write the data of the format {\it format} in the buffer {\it buf}. The method will write the data of the format {\it format} in the buffer {\it
buf} and return TRUE on success, FALSE on failure.
\membersection{wxDataObject::GetDataSize}\label{wxdataobjectgetdatasize} \membersection{wxDataObject::GetDataSize}\label{wxdataobjectgetdatasize}
@@ -80,16 +167,30 @@ The method will write the data of the format {\it format} in the buffer {\it buf
Returns the data size of the given format {\it format}. Returns the data size of the given format {\it format}.
\membersection{wxDataObject::GetFormatCount}\label{wxdataobjectgetformatcount}
\constfunc{virtual size\_t}{GetFormatCount}{\param{Direction}{ dir = Get}}
Return the number of available formats for rendering or setting the data.
\membersection{wxDataObject::GetPreferredFormat}\label{wxdataobjectgetpreferredformat} \membersection{wxDataObject::GetPreferredFormat}\label{wxdataobjectgetpreferredformat}
\constfunc{virtual wxDataFormat}{GetPreferredFormat}{\void} \constfunc{virtual wxDataFormat}{GetPreferredFormat}{\param{Direction}{ dir = Get}}
Returns the preferred format. Usually the first format in the list of available formats. Returns the preferred format for either rendering the data (if {\it dir} is
{\tt Get}, its default value) or for setting it. Usually this will be the
native format of the wxDataObject.
\membersection{wxDataObject::SetData}\label{wxdataobjectsetdata} \membersection{wxDataObject::SetData}\label{wxdataobjectsetdata}
\func{virtual bool}{SetData}{\param{const wxDataFormat\&}{ format}, \param{size_t}{ len}, \param{const void}{*buf} } \func{virtual bool}{SetData}{
\param{const wxDataFormat\&}{ format},
\param{size\_t}{ len},
\param{const void }{*buf} }
Set the data of the format {\it format} and the size {\it len} provided in the buffer {\it buf}. Set the data in the format {\it format} of the length {\it len} provided in the
buffer {\it buf}.
Returns TRUE on sucess, FALSE on failure.

View File

@@ -1,9 +1,18 @@
\section{\class{wxFileDataObject}}\label{wxfiledataobject} \section{\class{wxFileDataObject}}\label{wxfiledataobject}
wxFileDataObject is a specialization of wxDataObject for file names. wxFileDataObject is a specialization of \helpref{wxDataObject}{wxdataobject}
for file names. Unlike other predefined wxDataObject derivations, it only works
in one direction - the one of setting the data, i.e. the program can only
receive files dropped on it using it and there is no way (currently) to
initiate a drag and drop file operation.
\wxheading{Virtual functions to override}
None.
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxDataObjectSimple}{wxdataobjectsimple}
\helpref{wxDataObject}{wxdataobject} \helpref{wxDataObject}{wxdataobject}
\wxheading{Include files} \wxheading{Include files}
@@ -12,31 +21,23 @@ wxFileDataObject is a specialization of wxDataObject for file names.
\wxheading{See also} \wxheading{See also}
\helpref{wxDataObject}{wxdataobject},
\helpref{wxDataObjectSimple}{wxdataobjectsimple},
\helpref{wxTextDataObject}{wxtextdataobject},
\helpref{wxBitmapDataObject}{wxbitmapdataobject}
\helpref{wxDataObject}{wxdataobject} \helpref{wxDataObject}{wxdataobject}
\latexignore{\rtfignore{\wxheading{Members}}} \latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxFileDataObject::wxFileDataObject}\label{wxfiledataobjectwxfiledataobject} \membersection{wxFileDataObject}\label{wxfiledataobjectwxfiledataobject}
\func{}{wxFileDataObject}{\void} \func{}{wxFileDataObject}{\void}
Constructor. Constructor.
\membersection{wxFileDataObject::GetFormat}\label{wxfiledataobjectgetformat} \membersection{wxFileDataObject::GetFilenames}\label{wxfiledataobjectgetfilenames}
\constfunc{virtual wxDataFormat}{GetFormat}{\void} \constfunc{const wxArrayString\& }{GetFilenames}{\void}
Returns wxDF\_FILENAME. Returns the \helpref{array}{wxarraystring} of file names.
\membersection{wxFileDataObject::AddFile}\label{wxfiledataobjectaddfile}
\func{virtual void}{AddFile}{\param{const wxString\& }{file}}
Adds a filename to the data object.
\membersection{wxFileDataObject::GetFiles}\label{wxfiledataobjectgetfiles}
\constfunc{virtual wxString}{GetFiles}{\void}
Returns files as a zero-separated list.

View File

@@ -15,7 +15,18 @@ A static text control displays one or more lines of read-only text.
\wxheading{Window styles} \wxheading{Window styles}
There are no special styles for this control. \twocolwidtha{5cm}
\begin{twocollist}\itemsep=0pt
\twocolitem{\windowstyle{wxALIGN\_LEFT}}{Align the text to the left}
\twocolitem{\windowstyle{wxALIGN\_RIGHT}}{Align the text to the right}
\twocolitem{\windowstyle{wxALIGN\_CENTRE}}{Center the text (horisontally)}
\twocolitem{\windowstyle{wxST\_NO\_AUTORESIZE}}{By default, the control will
adjust its size to exactly fit to the size of the text when
\helpref{SetLabel}{wxstatictextsetlabel} is called. If this style flag is
given, the control will not change its size (this style is especially useful
with controls which also have wxALIGN\_RIGHT or CENTER style because otherwise
they won't make sense any longer after a call to SetLabel)}
\end{twocollist}
See also \helpref{window styles overview}{windowstyles}. See also \helpref{window styles overview}{windowstyles}.
@@ -75,7 +86,8 @@ Returns the contents of the control.
\func{virtual void}{SetLabel}{\param{const wxString\& }{ label}} \func{virtual void}{SetLabel}{\param{const wxString\& }{ label}}
Sets the static text label. Sets the static text label and updates the controls size to exactly fit the
label unless the control has wxST\_NO\_AUTORESIZE flag.
\wxheading{Parameters} \wxheading{Parameters}

View File

@@ -1,4 +1,4 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Name: tclipbrd.tex %% Name: tclipbrd.tex
%% Purpose: Data transfer (clipboard and drag and drop) overview %% Purpose: Data transfer (clipboard and drag and drop) overview
%% Author: Vadim Zeitlin %% Author: Vadim Zeitlin
@@ -7,7 +7,7 @@
%% RCS-ID: $Id$ %% RCS-ID: $Id$
%% Copyright: (c) Vadim Zeitlin %% Copyright: (c) Vadim Zeitlin
%% Licence: wxWindows licence %% Licence: wxWindows licence
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Clipboard and drag and drop overview}\label{wxclipboardonfigoverview} \section{Clipboard and drag and drop overview}\label{wxclipboardonfigoverview}
@@ -17,23 +17,24 @@ Classes: \helpref{wxDataObject}{wxdataobject},
\helpref{wxDropSource}{wxdropsource}, \helpref{wxDropSource}{wxdropsource},
\helpref{wxDropTarget}{wxdroptarget} \helpref{wxDropTarget}{wxdroptarget}
See also: \helpref{DnD sample}{samplednd}
This overview discusses data transfer through clipboard or drag and drop. In This overview discusses data transfer through clipboard or drag and drop. In
wxWindows, these two ways to transfer data (either between different wxWindows, these two ways to transfer data (either between different
applications or inside one and the same) are very similar which allows to applications or inside one and the same) are very similar which allows to
implement both of them using almost the same code - or in other implement both of them using almost the same code - or, in other
words, if you implement drag and drop support for your application, you get words, if you implement drag and drop support for your application, you get
clipboard support for free and vice versa. clipboard support for free and vice versa.
In the heart of both clipboard and drag and drop operations lies the In the heart of both clipboard and drag and drop operations lies the
\helpref{wxDataObject}{wxdataobject} class. The objects of this class (or, to be \helpref{wxDataObject}{wxdataobject} class. The objects of this class (or, to
precise, classes derived from it) represent the data which is being carried by be precise, classes derived from it) represent the data which is being carried
the mouse during drag and drop operation or copied to or pasted from the by the mouse during drag and drop operation or copied to or pasted from the
clipboard. wxDataObject is a "smart" piece of data clipboard. wxDataObject is a "smart" piece of data because it knows which
because it knows which formats it supports (see formats it supports (see GetFormatCount and GetAllFormats) and knows how to
GetFormatCount and GetAllFormats) and knows how to render render itself in any of them (see GetDataHere). It can also receive its value
itself in any of them (see GetDataHere). from the outside in a format it supports if it implements the SetData method.
It can also receive its value from the outside in a format it supports if it Please see the documentation of this class for more details.
implements the SetData method.
Both clipboard and drag and drop operations have two sides: the source and Both clipboard and drag and drop operations have two sides: the source and
target, the data provider and the data receiver. These which may be in the same target, the data provider and the data receiver. These which may be in the same
@@ -44,10 +45,10 @@ should do.
\subsection{The data provider (source) duties}{wxdataobjectsource} \subsection{The data provider (source) duties}{wxdataobjectsource}
The data provider is responsible for creating a The data provider is responsible for creating a
\helpref{wxDataObject}{wxdataobjectwxdataobject} containing the data to be \helpref{wxDataObject}{wxdataobject} containing the data to be
transfered. Then it should either pass it to the clipboard using transfered. Then it should either pass it to the clipboard using
\helpref{AddData}{wxclipboardadddata} or \helpref{SetData}{wxclipboardsetdata} \helpref{SetData}{wxclipboardsetdata} function or to
functions or to \helpref{wxDropSource}{wxdropsource} and call \helpref{wxDropSource}{wxdropsource} and call
\helpref{DoDragDrop}{wxdropsourcedodragdrop} function. \helpref{DoDragDrop}{wxdropsourcedodragdrop} function.
The only (but important) difference is that the object for the clipboard The only (but important) difference is that the object for the clipboard
@@ -74,9 +75,10 @@ data formats you need and pass it as argument to
no data in (any of) the supported format(s) is available. If it returns {\tt no data in (any of) the supported format(s) is available. If it returns {\tt
TRUE}, the data has been successfully transfered to wxDataObject. TRUE}, the data has been successfully transfered to wxDataObject.
{\bf TODO} document drag and drop side when the API is finalised For drag and drop case, the \helpref{wxDropTarget::OnData}{wxdroptargetondata}
virtual function will be called when a data object is dropped, from which the
data itself may be requested by calling
\helpref{wxDropTarget::GetData}{wxdroptargetwxdroptarget} method which fills
the data object.
% !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
% Vadim, please remember the new line at the end of each file. Please
% also remember to compile the .hlp file to check for bad references etc.,
% before checking in. I have removed references that were unresolved. - JACS

View File

@@ -4,6 +4,7 @@
This chapter contains a selection of topic overviews. This chapter contains a selection of topic overviews.
\input tsamples.tex
\input tapp.tex \input tapp.tex
\input tstring.tex \input tstring.tex
\input tcontain.tex \input tcontain.tex
@@ -38,7 +39,6 @@ This chapter contains a selection of topic overviews.
\input tvalidat.tex \input tvalidat.tex
\input texpr.tex \input texpr.tex
\input tgrid.tex \input tgrid.tex
\input tdnd.tex
\input tthreads.tex \input tthreads.tex
\input tfile.tex \input tfile.tex
\input ti18n.tex \input ti18n.tex
@@ -46,3 +46,6 @@ This chapter contains a selection of topic overviews.
\input tusage.tex \input tusage.tex
\input ttips.tex \input ttips.tex
\input fs.tex \input fs.tex
% \input tdnd.tex

View File

@@ -2,15 +2,27 @@
wxTextDataObject is a specialization of wxDataObject for text data. It can be wxTextDataObject is a specialization of wxDataObject for text data. It can be
used without change to paste data into the \helpref{wxClipboard}{wxclipboard} used without change to paste data into the \helpref{wxClipboard}{wxclipboard}
or a \helpref{wxDropSource}{wxdropsource}. A user may wish to derive a new class or a \helpref{wxDropSource}{wxdropsource}. A user may wish to derive a new
from this class for providing text on-demand in order to minimize memory consumption class from this class for providing text on-demand in order to minimize memory
when offering data in several formats, such as plain text and RTF. consumption when offering data in several formats, such as plain text and RTF
because by default the text is stored in a string in this class, but it might
as well be generated when requested. For this,
\helpref{GetTextLength}{wxtextdataobjectgettextlength} and
\helpref{GetText}{wxtextdataobjectgettext} will have to be overridden.
In order to offer text data on-demand \helpref{GetSize}{wxtextdataobjectgetsize} Note that if you already have the text inside a string, you will not achieve
and \helpref{WriteData}{wxtextdataobjectwritedata} will have to be overridden. any efficiency gain by overriding these functions because copying wxStrings is
already a very efficient operation (data is not actualyl copied because
wxStrings are reference counted).
\wxheading{Virtual functions to override}
This class may be used as is, but all of data transfer functions may be
overridden to increase efficiency.
\wxheading{Derived from} \wxheading{Derived from}
\helpref{wxDataObjectSimple}{wxdataobjectsimple}
\helpref{wxDataObject}{wxdataobject} \helpref{wxDataObject}{wxdataobject}
\wxheading{Include files} \wxheading{Include files}
@@ -19,25 +31,24 @@ and \helpref{WriteData}{wxtextdataobjectwritedata} will have to be overridden.
\wxheading{See also} \wxheading{See also}
\helpref{wxDataObject}{wxdataobject} \helpref{Clipboard and drag and drop overview}{wxclipboardonfigoverview},
\helpref{wxDataObject}{wxdataobject},
\helpref{wxDataObjectSimple}{wxdataobjectsimple},
\helpref{wxFileDataObject}{wxfiledataobject},
\helpref{wxBitmapDataObject}{wxbitmapdataobject}
\latexignore{\rtfignore{\wxheading{Members}}} \latexignore{\rtfignore{\wxheading{Members}}}
\membersection{wxTextDataObject::wxTextDataObject}\label{wxtextdataobjectwxtextdataobject} \membersection{wxTextDataObject::wxTextDataObject}\label{wxtextdataobjectwxtextdataobject}
\func{}{wxTextDataObject}{\void} \func{}{wxTextDataObject}{\param{const wxString\& }{text = wxEmptyString}}
Default constructor. Call \helpref{SetText}{wxtextdataobjectsettext} later Constructor, may be used to initialise the text (otherwise
or override \helpref{WriteData}{wxtextdataobjectwritedata} and \helpref{SetText}{wxtextdataobjectsettext} should be used later)
\helpref{GetSize}{wxtextdataobjectgetsize} for providing data on-demand.
\func{}{wxTextDataObject}{\param{const wxString\& }{strText}} \membersection{wxTextDataObject::GetTextLength}\label{wxtextdataobjectgettextlength}
Constructor, passing text. \constfunc{virtual size\_t}{GetTextLength}{\void}
\membersection{wxTextDataObject::GetSize}\label{wxtextdataobjectgetsize}
\constfunc{virtual size\_t}{GetSize}{\void}
Returns the data size. By default, returns the size of the text data Returns the data size. By default, returns the size of the text data
set in the constructor or using \helpref{SetText}{wxtextdataobjectsettext}. set in the constructor or using \helpref{SetText}{wxtextdataobjectsettext}.
@@ -59,25 +70,8 @@ the \helpref{wxClipboard}{wxclipboard}.
\func{virtual void}{SetText}{\param{const wxString\& }{strText}} \func{virtual void}{SetText}{\param{const wxString\& }{strText}}
Sets the text associated with the data object. This method is called Sets the text associated with the data object. This method is called
internally when retrieving data from the \helpref{wxClipboard}{wxclipboard} when the data object receives the data and, by default, copies the text into
and may be used to paste data to the clipboard directly (instead of the member variable. If you want to process the text on the fly you may wish to
on-demand). override this function.
\membersection{wxTextDataObject::WriteData}\label{wxtextdataobjectwritedata}
\constfunc{virtual void}{WriteData}{\param{void}{*dest} }
Write the data owned by this class to {\it dest}. By default, this
calls \helpref{WriteString}{wxtextdataobjectwritestring} with the string
set in the constructor or using \helpref{SetText}{wxtextdataobjectsettext}.
This can be overridden to provide text data on-demand; in this case
\helpref{WriteString}{wxtextdataobjectwritestring} must be called from
within the overriding WriteData() method.
\membersection{wxTextDataObject::WriteString}\label{wxtextdataobjectwritestring}
\constfunc{void}{WriteString}{\param{const wxString\& }{str}\param{void}{*dest} }
Writes the the string {\it str} to {\it dest}. This method must be called
from \helpref{WriteData}{wxtextdataobjectwritedata}.

View File

@@ -1,14 +1,14 @@
[OPTIONS] [OPTIONS]
BMROOT=d:\wx2\wxWindows\docs\latex\wx ; Assume that bitmaps are where the source is BMROOT=L:\wxWindows\docs\latex\wx ; Assume that bitmaps are where the source is
TITLE=wxWindows Manual TITLE=wxWindows Manual
CONTENTS=Contents CONTENTS=Contents
COMPRESS=HIGH COMPRESS=HIGH
[FILES] [FILES]
wx.rtf Wx.rtf
[CONFIG] [CONFIG]
CreateButton("Up", "&Up", "JumpId(`wx.hlp', `Contents')") CreateButton("Up", "&Up", "JumpId(`Wx.hlp', `Contents')")
BrowseButtons() BrowseButtons()
[MAP] [MAP]

View File

@@ -51,10 +51,6 @@ public:
long m_style; long m_style;
wxWindow *m_invokingWindow; wxWindow *m_invokingWindow;
#if 0 // seems to be unused (VZ)
wxMenuList& GetMenus() { return m_menus; }
#endif // 0
private: private:
DECLARE_DYNAMIC_CLASS(wxMenuBar) DECLARE_DYNAMIC_CLASS(wxMenuBar)
}; };
@@ -63,92 +59,34 @@ private:
// wxMenu // wxMenu
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class wxMenu : public wxEvtHandler class wxMenu : public wxMenuBase
{ {
DECLARE_DYNAMIC_CLASS(wxMenu)
public: public:
wxMenu( const wxString& title, const wxFunction func) // ctors & dtor
{ wxMenu(const wxString& title, long style = 0)
Init(title, 0, func); : wxMenuBase(title, style) { Init(); }
}
wxMenu( long style )
{
Init( wxEmptyString, style );
}
wxMenu( const wxString& title = wxEmptyString, long style = 0 )
{
Init(title, style);
}
~wxMenu(); wxMenu(long style = 0) : wxMenuBase(style) { Init(); }
// title virtual ~wxMenu();
void SetTitle(const wxString& label);
const wxString GetTitle() const;
// menu creation // implement base class virtuals
void AppendSeparator(); virtual bool DoAppend(wxMenuItem *item);
void Append(int id, const wxString &item, virtual bool DoInsert(size_t pos, wxMenuItem *item);
const wxString &helpStr = "", bool checkable = FALSE); virtual wxMenuItem *DoRemove(wxMenuItem *item);
void Append(int id, const wxString &item,
wxMenu *subMenu, const wxString &helpStr = "" );
void Append(wxMenuItem *pItem);
void Break() { }
// delete item. don't delete the wxMenu if it's a submenu // TODO: virtual void SetTitle(const wxString& title);
void Delete( int id );
// find item by name/id
int FindItem( const wxString itemString ) const;
wxMenuItem *FindItem( int id ) const;
// get/set item's state
void Enable( int id, bool enable );
bool IsEnabled( int id ) const;
void Check( int id, bool check );
bool IsChecked( int id ) const;
void SetLabel( int id, const wxString &label );
wxString GetLabel( int id ) const;
// helpstring
virtual void SetHelpString(int id, const wxString& helpString);
virtual wxString GetHelpString(int id) const ;
// accessors
wxList& GetItems() { return m_items; }
void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; }
wxEvtHandler *GetEventHandler() { return m_eventHandler; }
void SetClientData( void* clientData ) { m_clientData = clientData; }
void* GetClientData() const { return m_clientData; }
// Updates the UI for a menu and all submenus recursively.
// source is the object that has the update event handlers
// defined for it. If NULL, the menu or associated window
// will be used.
void UpdateUI(wxEvtHandler* source = (wxEvtHandler*) NULL);
wxMenuItem *FindItemForId( int id ) const { return FindItem( id ); }
wxFunction GetCallback() const { return m_callback; }
void Callback(const wxFunction func) { m_callback = func; }
wxFunction m_callback;
#ifdef WXWIN_COMPATIBILITY #ifdef WXWIN_COMPATIBILITY
wxMenu(const wxString& title, const wxFunction func)
// compatibility: these functions are deprecated : wxMenuBase(title)
bool Enabled(int id) const { return IsEnabled(id); } {
bool Checked(int id) const { return IsChecked(id); } Callback(func);
}
#endif // WXWIN_COMPATIBILITY #endif // WXWIN_COMPATIBILITY
// implementation // implementation
int FindMenuIdByMenuItem( GtkWidget *menuItem ) const; int FindMenuIdByMenuItem( GtkWidget *menuItem ) const;
void SetInvokingWindow( wxWindow *win );
wxWindow *GetInvokingWindow();
// implementation GTK only // implementation GTK only
GtkWidget *m_menu; // GtkMenu GtkWidget *m_menu; // GtkMenu
@@ -156,21 +94,11 @@ public:
GtkAccelGroup *m_accel; GtkAccelGroup *m_accel;
GtkItemFactory *m_factory; GtkItemFactory *m_factory;
// used by wxMenuBar
long GetStyle(void) const { return m_style; }
private: private:
// common code for both constructors: // common code for all constructors:
void Init( const wxString& title, void Init();
long style,
const wxFunction func = (wxFunction) NULL );
wxString m_title; DECLARE_DYNAMIC_CLASS(wxMenu)
wxList m_items;
wxWindow *m_invokingWindow;
wxEvtHandler *m_eventHandler;
void *m_clientData;
long m_style;
}; };
#endif // __GTKMENUH__ #endif // __GTKMENUH__

View File

@@ -31,10 +31,15 @@ public:
// implement base class virtuals // implement base class virtuals
virtual void SetText( const wxString& str ); virtual void SetText( const wxString& str );
virtual wxString GetLabel() const;
virtual void Enable( bool enable = TRUE ); virtual void Enable( bool enable = TRUE );
virtual void Check( bool check = TRUE ); virtual void Check( bool check = TRUE );
virtual bool IsChecked() const; virtual bool IsChecked() const;
#if wxUSE_ACCEL
virtual wxAcceleratorEntry *GetAccel() const;
#endif // wxUSE_ACCEL
// implementation // implementation
void SetMenuItem(GtkWidget *menuItem) { m_menuItem = menuItem; } void SetMenuItem(GtkWidget *menuItem) { m_menuItem = menuItem; }
GtkWidget *GetMenuItem() const { return m_menuItem; } GtkWidget *GetMenuItem() const { return m_menuItem; }

View File

@@ -51,10 +51,6 @@ public:
long m_style; long m_style;
wxWindow *m_invokingWindow; wxWindow *m_invokingWindow;
#if 0 // seems to be unused (VZ)
wxMenuList& GetMenus() { return m_menus; }
#endif // 0
private: private:
DECLARE_DYNAMIC_CLASS(wxMenuBar) DECLARE_DYNAMIC_CLASS(wxMenuBar)
}; };
@@ -63,92 +59,34 @@ private:
// wxMenu // wxMenu
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
class wxMenu : public wxEvtHandler class wxMenu : public wxMenuBase
{ {
DECLARE_DYNAMIC_CLASS(wxMenu)
public: public:
wxMenu( const wxString& title, const wxFunction func) // ctors & dtor
{ wxMenu(const wxString& title, long style = 0)
Init(title, 0, func); : wxMenuBase(title, style) { Init(); }
}
wxMenu( long style )
{
Init( wxEmptyString, style );
}
wxMenu( const wxString& title = wxEmptyString, long style = 0 )
{
Init(title, style);
}
~wxMenu(); wxMenu(long style = 0) : wxMenuBase(style) { Init(); }
// title virtual ~wxMenu();
void SetTitle(const wxString& label);
const wxString GetTitle() const;
// menu creation // implement base class virtuals
void AppendSeparator(); virtual bool DoAppend(wxMenuItem *item);
void Append(int id, const wxString &item, virtual bool DoInsert(size_t pos, wxMenuItem *item);
const wxString &helpStr = "", bool checkable = FALSE); virtual wxMenuItem *DoRemove(wxMenuItem *item);
void Append(int id, const wxString &item,
wxMenu *subMenu, const wxString &helpStr = "" );
void Append(wxMenuItem *pItem);
void Break() { }
// delete item. don't delete the wxMenu if it's a submenu // TODO: virtual void SetTitle(const wxString& title);
void Delete( int id );
// find item by name/id
int FindItem( const wxString itemString ) const;
wxMenuItem *FindItem( int id ) const;
// get/set item's state
void Enable( int id, bool enable );
bool IsEnabled( int id ) const;
void Check( int id, bool check );
bool IsChecked( int id ) const;
void SetLabel( int id, const wxString &label );
wxString GetLabel( int id ) const;
// helpstring
virtual void SetHelpString(int id, const wxString& helpString);
virtual wxString GetHelpString(int id) const ;
// accessors
wxList& GetItems() { return m_items; }
void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; }
wxEvtHandler *GetEventHandler() { return m_eventHandler; }
void SetClientData( void* clientData ) { m_clientData = clientData; }
void* GetClientData() const { return m_clientData; }
// Updates the UI for a menu and all submenus recursively.
// source is the object that has the update event handlers
// defined for it. If NULL, the menu or associated window
// will be used.
void UpdateUI(wxEvtHandler* source = (wxEvtHandler*) NULL);
wxMenuItem *FindItemForId( int id ) const { return FindItem( id ); }
wxFunction GetCallback() const { return m_callback; }
void Callback(const wxFunction func) { m_callback = func; }
wxFunction m_callback;
#ifdef WXWIN_COMPATIBILITY #ifdef WXWIN_COMPATIBILITY
wxMenu(const wxString& title, const wxFunction func)
// compatibility: these functions are deprecated : wxMenuBase(title)
bool Enabled(int id) const { return IsEnabled(id); } {
bool Checked(int id) const { return IsChecked(id); } Callback(func);
}
#endif // WXWIN_COMPATIBILITY #endif // WXWIN_COMPATIBILITY
// implementation // implementation
int FindMenuIdByMenuItem( GtkWidget *menuItem ) const; int FindMenuIdByMenuItem( GtkWidget *menuItem ) const;
void SetInvokingWindow( wxWindow *win );
wxWindow *GetInvokingWindow();
// implementation GTK only // implementation GTK only
GtkWidget *m_menu; // GtkMenu GtkWidget *m_menu; // GtkMenu
@@ -156,21 +94,11 @@ public:
GtkAccelGroup *m_accel; GtkAccelGroup *m_accel;
GtkItemFactory *m_factory; GtkItemFactory *m_factory;
// used by wxMenuBar
long GetStyle(void) const { return m_style; }
private: private:
// common code for both constructors: // common code for all constructors:
void Init( const wxString& title, void Init();
long style,
const wxFunction func = (wxFunction) NULL );
wxString m_title; DECLARE_DYNAMIC_CLASS(wxMenu)
wxList m_items;
wxWindow *m_invokingWindow;
wxEvtHandler *m_eventHandler;
void *m_clientData;
long m_style;
}; };
#endif // __GTKMENUH__ #endif // __GTKMENUH__

View File

@@ -31,10 +31,15 @@ public:
// implement base class virtuals // implement base class virtuals
virtual void SetText( const wxString& str ); virtual void SetText( const wxString& str );
virtual wxString GetLabel() const;
virtual void Enable( bool enable = TRUE ); virtual void Enable( bool enable = TRUE );
virtual void Check( bool check = TRUE ); virtual void Check( bool check = TRUE );
virtual bool IsChecked() const; virtual bool IsChecked() const;
#if wxUSE_ACCEL
virtual wxAcceleratorEntry *GetAccel() const;
#endif // wxUSE_ACCEL
// implementation // implementation
void SetMenuItem(GtkWidget *menuItem) { m_menuItem = menuItem; } void SetMenuItem(GtkWidget *menuItem) { m_menuItem = menuItem; }
GtkWidget *GetMenuItem() const { return m_menuItem; } GtkWidget *GetMenuItem() const { return m_menuItem; }

View File

@@ -20,20 +20,204 @@
// headers // headers
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "wx/list.h" // for wxMenuList #include "wx/list.h" // for "template" list classes
#include "wx/window.h" // base class for wxMenuBar #include "wx/window.h" // base class for wxMenuBar
// also include this one to ensure compatibility with old code which only
// included wx/menu.h
#include "wx/menuitem.h"
class WXDLLEXPORT wxMenu; class WXDLLEXPORT wxMenu;
class WXDLLEXPORT wxMenuBar; class WXDLLEXPORT wxMenuBar;
class WXDLLEXPORT wxMenuItem; class WXDLLEXPORT wxMenuItem;
// pseudo template list classes
WX_DECLARE_LIST(wxMenu, wxMenuList);
WX_DECLARE_LIST(wxMenuItem, wxMenuItemList);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxMenu // wxMenu
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// for now, it's in platform-specific file class WXDLLEXPORT wxMenuBase : public wxEvtHandler
{
public:
// create a menu
static wxMenu *New(const wxString& title = wxEmptyString, long style = 0);
WX_DECLARE_LIST(wxMenu, wxMenuList); // ctors
wxMenuBase(const wxString& title, long style = 0) : m_title(title)
{ Init(style); }
wxMenuBase(long style = 0)
{ Init(style); }
// dtor deletes all the menu items we own
virtual ~wxMenuBase();
// menu construction
// -----------------
// append a separator to the menu
void AppendSeparator() { Append(wxID_SEPARATOR, wxEmptyString); }
// append a normal item to the menu
void Append(int id,
const wxString& text,
const wxString& help = wxEmptyString,
bool isCheckable = FALSE)
{
DoAppend(wxMenuItem::New((wxMenu *)this, id, text, help, isCheckable));
}
// append a submenu
void Append(int id,
const wxString& text,
wxMenu *submenu,
const wxString& help = wxEmptyString)
{
DoAppend(wxMenuItem::New((wxMenu *)this, id, text, help, FALSE, submenu));
}
// the most generic form of Append() - append anything
void Append(wxMenuItem *item) { DoAppend(item); }
// insert a break in the menu (only works when appending the items, not
// inserting them)
virtual void Break() { }
// insert an item before given position
bool Insert(size_t pos, wxMenuItem *item);
// detach an item from the menu, but don't delete it so that it can be
// added back later (but if it's not, the caller is responsible for
// deleting it!)
wxMenuItem *Remove(int id) { return Remove(FindChildItem(id)); }
wxMenuItem *Remove(wxMenuItem *item);
// delete an item from the menu (submenus are not destroyed by this
// function, see Destroy)
bool Delete(int id) { return Delete(FindChildItem(id)); }
bool Delete(wxMenuItem *item);
// delete the item from menu and destroy it (if it's a submenu)
bool Destroy(int id) { return Destroy(FindChildItem(id)); }
bool Destroy(wxMenuItem *item);
// menu items access
// -----------------
// get the items
size_t GetMenuItemCount() const { return m_items.GetCount(); }
const wxMenuItemList& GetMenuItems() const { return m_items; }
wxMenuItemList& GetMenuItems() { return m_items; }
// search
virtual int FindItem(const wxString& itemString) const;
wxMenuItem* FindItem(int id, wxMenu **menu = NULL) const;
// get/set items attributes
void Enable(int id, bool enable);
bool IsEnabled(int id) const;
void Check(int id, bool check);
bool IsChecked(int id) const;
void SetLabel(int id, const wxString& label);
wxString GetLabel(int id) const;
virtual void SetHelpString(int id, const wxString& helpString);
virtual wxString GetHelpString(int id) const;
// misc accessors
// --------------
// the title
virtual void SetTitle(const wxString& title) { m_title = title; }
const wxString GetTitle() const { return m_title; }
// client data
void SetClientData(void* clientData) { m_clientData = clientData; }
void* GetClientData() const { return m_clientData; }
// event handler
void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; }
wxEvtHandler *GetEventHandler() const { return m_eventHandler; }
// invoking window
void SetInvokingWindow(wxWindow *win) { m_invokingWindow = win; }
wxWindow *GetInvokingWindow() const { return m_invokingWindow; }
// style
long GetStyle() const { return m_style; }
// implementation helpers
// ----------------------
// Updates the UI for a menu and all submenus recursively. source is the
// object that has the update event handlers defined for it. If NULL, the
// menu or associated window will be used.
void UpdateUI(wxEvtHandler* source = (wxEvtHandler*)NULL);
// is the menu attached to a menu bar (or is it a popup one)?
bool IsAttached() const { return m_menuBar != NULL; }
// set/get the parent of this menu
void SetParent(wxMenu *parent) { m_menuParent = parent; }
wxMenu *GetParent() const { return m_menuParent; }
#if WXWIN_COMPATIBILITY
// compatibility: these functions are deprecated, use the new ones instead
bool Enabled(int id) const { return IsEnabled(id); }
bool Checked(int id) const { return IsChecked(id); }
wxMenuItem* FindItemForId(int itemId, wxMenu **itemMenu) const
{ return FindItem(itemId, itemMenu); }
wxList& GetItems() const { return (wxList &)m_items; }
// wxWin 1.6x compatible menu event handling
wxFunction GetCallback() const { return m_callback; }
void Callback(const wxFunction func) { m_callback = func; }
wxFunction m_callback;
#endif // WXWIN_COMPATIBILITY
protected:
// virtuals to override in derived classes
// ---------------------------------------
virtual bool DoAppend(wxMenuItem *item);
virtual bool DoInsert(size_t pos, wxMenuItem *item);
virtual wxMenuItem *DoRemove(wxMenuItem *item);
virtual bool DoDelete(wxMenuItem *item);
virtual bool DoDestroy(wxMenuItem *item);
// helpers
// -------
// common part of all ctors
void Init(long style);
// unlike FindItem(), this function doesn't recurse but only looks through
// our direct children and also may return the index of the found child if
// pos != NULL
wxMenuItem *FindChildItem(int id, size_t *pos = NULL) const;
protected:
wxMenuBar *m_menuBar; // menubar we belong to or NULL
wxMenu *m_menuParent; // parent menu or NULL
wxString m_title; // the menu title or label
wxMenuItemList m_items; // the list of menu items
wxWindow *m_invokingWindow; // for popup menus
void *m_clientData; // associated with the menu
long m_style; // combination of wxMENU_XXX flags
wxEvtHandler *m_eventHandler; // a pluggable in event handler
};
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxMenuBar // wxMenuBar
@@ -122,7 +306,7 @@ public:
// compatibility only: these functions are deprecated, use the new ones // compatibility only: these functions are deprecated, use the new ones
// instead // instead
#ifdef WXWIN_COMPATIBILITY #if WXWIN_COMPATIBILITY
bool Enabled(int id) const { return IsEnabled(id); } bool Enabled(int id) const { return IsEnabled(id); }
bool Checked(int id) const { return IsChecked(id); } bool Checked(int id) const { return IsChecked(id); }
@@ -161,9 +345,5 @@ protected:
#endif #endif
#endif // wxUSE_BASE_CLASSES_ONLY/!wxUSE_BASE_CLASSES_ONLY #endif // wxUSE_BASE_CLASSES_ONLY/!wxUSE_BASE_CLASSES_ONLY
// also include this one to ensure compatibility with old code which only
// included wx/menu.h
#include "wx/menuitem.h"
#endif #endif
// _WX_MENU_H_BASE_ // _WX_MENU_H_BASE_

View File

@@ -33,6 +33,7 @@
// forward declarations // forward declarations
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxAcceleratorEntry;
class WXDLLEXPORT wxMenuItem; class WXDLLEXPORT wxMenuItem;
class WXDLLEXPORT wxMenu; class WXDLLEXPORT wxMenu;
@@ -52,6 +53,9 @@ public:
bool isCheckable = FALSE, bool isCheckable = FALSE,
wxMenu *subMenu = (wxMenu *)NULL); wxMenu *subMenu = (wxMenu *)NULL);
// destruction: wxMenuItem will delete its submenu
virtual ~wxMenuItemBase();
// the menu we're in // the menu we're in
wxMenu *GetMenu() const { return m_parentMenu; } wxMenu *GetMenu() const { return m_parentMenu; }
@@ -60,8 +64,14 @@ public:
int GetId() const { return m_id; } int GetId() const { return m_id; }
bool IsSeparator() const { return m_id == wxID_SEPARATOR; } bool IsSeparator() const { return m_id == wxID_SEPARATOR; }
// the item's text (or name, or label...) // the item's text (or name)
//
// NB: the item's text includes the accelerators and mnemonics info (if
// any), i.e. it may contain '&' or '_' or "\t..." and thus is
// different from the item's label which only contains the text shown
// in the menu
virtual void SetText(const wxString& str) { m_text = str; } virtual void SetText(const wxString& str) { m_text = str; }
virtual wxString GetLabel() const { return m_text; }
const wxString& GetText() const { return m_text; } const wxString& GetText() const { return m_text; }
// what kind of menu item we are // what kind of menu item we are
@@ -75,13 +85,24 @@ public:
// state // state
virtual void Enable(bool enable = TRUE) { m_isEnabled = enable; } virtual void Enable(bool enable = TRUE) { m_isEnabled = enable; }
virtual bool IsEnabled() const { return m_isEnabled; } virtual bool IsEnabled() const { return m_isEnabled; }
virtual void Check(bool check = TRUE) { m_isChecked = check; } virtual void Check(bool check = TRUE) { m_isChecked = check; }
virtual bool IsChecked() const { return m_isChecked; } virtual bool IsChecked() const { return m_isChecked; }
void Toggle() { Check(!m_isChecked); }
// help string (displayed in the status bar by default) // help string (displayed in the status bar by default)
void SetHelp(const wxString& str) { m_help = str; } void SetHelp(const wxString& str) { m_help = str; }
const wxString& GetHelp() const { return m_help; } const wxString& GetHelp() const { return m_help; }
#if wxUSE_ACCEL
// get our accelerator or NULL (caller must delete the pointer)
virtual wxAcceleratorEntry *GetAccel() const { return NULL; }
// set the accel for this item - this may also be done indirectly with
// SetText()
virtual void SetAccel(wxAcceleratorEntry *accel);
#endif // wxUSE_ACCEL
// compatibility only, use new functions in the new code // compatibility only, use new functions in the new code
void SetName(const wxString& str) { SetText(str); } void SetName(const wxString& str) { SetText(str); }
const wxString& GetName() const { return GetText(); } const wxString& GetName() const { return GetText(); }

View File

@@ -16,179 +16,97 @@
#pragma interface "menu.h" #pragma interface "menu.h"
#endif #endif
#include "wx/defs.h"
#include "wx/event.h"
#include "wx/dynarray.h"
#include "wx/string.h"
#if wxUSE_ACCEL #if wxUSE_ACCEL
#include "wx/accel.h" #include "wx/accel.h"
#include "wx/dynarray.h"
WX_DEFINE_EXPORTED_ARRAY(wxAcceleratorEntry *, wxAcceleratorArray);
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
class WXDLLEXPORT wxMenuItem;
class WXDLLEXPORT wxMenuBar;
class WXDLLEXPORT wxMenu;
class WXDLLEXPORT wxFrame; class WXDLLEXPORT wxFrame;
WXDLLEXPORT_DATA(extern const wxChar*) wxEmptyString;
WX_DEFINE_EXPORTED_ARRAY(wxAcceleratorEntry *, wxAcceleratorArray);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Menu // Menu
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxMenu : public wxEvtHandler class WXDLLEXPORT wxMenu : public wxMenuBase
{ {
DECLARE_DYNAMIC_CLASS(wxMenu)
public: public:
// ctors & dtor // ctors & dtor
wxMenu(const wxString& title, wxMenu(const wxString& title, long style = 0)
const wxFunction func) : wxMenuBase(title, style) { Init(); }
{
Init(title, func);
}
wxMenu( long WXUNUSED(style) ) wxMenu(long style = 0) : wxMenuBase(style) { Init(); }
{
Init( wxEmptyString );
}
wxMenu(const wxString& title = wxEmptyString, long WXUNUSED(style) = 0)
{
Init(title);
}
virtual ~wxMenu(); virtual ~wxMenu();
// construct menu // implement base class virtuals
// append a separator to the menu virtual bool DoAppend(wxMenuItem *item);
void AppendSeparator(); virtual bool DoInsert(size_t pos, wxMenuItem *item);
// append a normal item to the menu virtual wxMenuItem *DoRemove(wxMenuItem *item);
void Append(int id, const wxString& label,
const wxString& helpString = wxEmptyString,
bool checkable = FALSE);
// append a submenu
void Append(int id, const wxString& label,
wxMenu *submenu,
const wxString& helpString = wxEmptyString);
// append anything (create wxMenuItem first)
void Append(wxMenuItem *pItem);
// insert a break in the menu virtual void Break();
void Break();
// delete an item virtual void SetTitle(const wxString& title);
// If it's a submenu, menu is not destroyed.
// VZ: why? shouldn't it return "wxMenu *" then?
void Delete(int id);
// client data
void SetClientData(void* clientData) { m_clientData = clientData; }
void* GetClientData() const { return m_clientData; }
// menu item control
// enable/disable item
void Enable(int id, bool enable);
// TRUE if enabled
bool IsEnabled(int id) const;
// check/uncheck item - only for checkable items, of course
void Check(int id, bool check);
// TRUE if checked
bool IsChecked(int id) const;
// other properties
// the menu title
void SetTitle(const wxString& label);
const wxString GetTitle() const;
// the item label
void SetLabel(int id, const wxString& label);
wxString GetLabel(int id) const;
// help string
virtual void SetHelpString(int id, const wxString& helpString);
virtual wxString GetHelpString(int id) const;
// get the list of items
wxList& GetItems() const { return (wxList &)m_menuItems; }
// find item
// returns id of the item matching the given string or wxNOT_FOUND
virtual int FindItem(const wxString& itemString) const;
// returns NULL if not found
wxMenuItem* FindItem(int id) const { return FindItemForId(id); }
// find wxMenuItem by ID, and item's menu too if itemMenu is !NULL
wxMenuItem *FindItemForId(int itemId, wxMenu **itemMenu = NULL) const;
// Updates the UI for a menu and all submenus recursively. source is the
// object that has the update event handlers defined for it. If NULL, the
// menu or associated window will be used.
void UpdateUI(wxEvtHandler* source = (wxEvtHandler*)NULL);
// MSW-specific
bool ProcessCommand(wxCommandEvent& event); bool ProcessCommand(wxCommandEvent& event);
void SetEventHandler(wxEvtHandler *handler) { m_eventHandler = handler; } #ifdef WXWIN_COMPATIBILITY
wxEvtHandler *GetEventHandler() const { return m_eventHandler; } wxMenu(const wxString& title, const wxFunction func)
: wxMenuBase(title)
{
Callback(func);
}
#endif // WXWIN_COMPATIBILITY
// implementation only from now on
// -------------------------------
// IMPLEMENTATION
bool MSWCommand(WXUINT param, WXWORD id); bool MSWCommand(WXUINT param, WXWORD id);
void SetInvokingWindow(wxWindow *pWin) { m_pInvokingWindow = pWin; }
wxWindow *GetInvokingWindow() const { return m_pInvokingWindow; }
// semi-private accessors // semi-private accessors
// get the window which contains this menu // get the window which contains this menu
wxWindow *GetWindow() const; wxWindow *GetWindow() const;
// get the menu handle // get the menu handle
WXHMENU GetHMenu() const; WXHMENU GetHMenu() const { return m_hMenu; }
// only for wxMenuBar // attach/detach menu to/from wxMenuBar
void Attach(wxMenuBar *menubar); void Attach(wxMenuBar *menubar);
void Detach(); void Detach();
#if wxUSE_ACCEL #if wxUSE_ACCEL
// called by wxMenuBar to build its accel table from the accels of all menus
bool HasAccels() const { return !m_accels.IsEmpty(); }
size_t GetAccelCount() const { return m_accels.GetCount(); } size_t GetAccelCount() const { return m_accels.GetCount(); }
size_t CopyAccels(wxAcceleratorEntry *accels) const; size_t CopyAccels(wxAcceleratorEntry *accels) const;
// called by wxMenuItem when its accels changes
void UpdateAccel(wxMenuItem *item);
// helper used by wxMenu itself (returns the index in m_accels)
int FindAccel(int id) const;
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
wxFunction GetCallback() const { return m_callback; }
void Callback(const wxFunction func) { m_callback = func; }
wxFunction m_callback;
#ifdef WXWIN_COMPATIBILITY
// compatibility: these functions are deprecated
bool Enabled(int id) const { return IsEnabled(id); }
bool Checked(int id) const { return IsChecked(id); }
#endif // WXWIN_COMPATIBILITY
private: private:
// common part of all ctors // common part of all ctors
void Init(const wxString& title, const wxFunction func = NULL ); void Init();
// common part of Append/Insert (behaves as Append is pos == (size_t)-1)
bool DoInsertOrAppend(wxMenuItem *item, size_t pos = (size_t)-1);
// if TRUE, insert a breal before appending the next item
bool m_doBreak; bool m_doBreak;
// This is used when m_hMenu is NULL because we don't want to // the menu handle of this menu
// delete it in ~wxMenu (it's been added to a parent menu).
// But we'll still need the handle for other purposes.
// Might be better to have a flag saying whether it's deleteable or not.
WXHMENU m_savehMenu ; // Used for Enable() on popup
WXHMENU m_hMenu; WXHMENU m_hMenu;
int m_noItems;
wxString m_title;
wxMenu * m_topLevelMenu;
wxMenuBar * m_menuBar;
wxList m_menuItems;
wxEvtHandler * m_eventHandler;
wxWindow *m_pInvokingWindow;
void* m_clientData;
#if wxUSE_ACCEL #if wxUSE_ACCEL
// the accelerators for our menu items // the accelerators for our menu items
wxAcceleratorArray m_accels; wxAcceleratorArray m_accels;
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
DECLARE_DYNAMIC_CLASS(wxMenu)
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -243,8 +161,11 @@ public:
void Attach(wxFrame *frame); void Attach(wxFrame *frame);
#if wxUSE_ACCEL #if wxUSE_ACCEL
// get the accel table for the menus // get the accel table for all the menus
const wxAcceleratorTable& GetAccelTable() const { return m_accelTable; } const wxAcceleratorTable& GetAccelTable() const { return m_accelTable; }
// update the accel table (must be called after adding/deletign a menu)
void RebuildAccelTable();
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
// get the menu handle // get the menu handle

View File

@@ -45,12 +45,17 @@ public:
// override base class virtuals // override base class virtuals
virtual void SetText(const wxString& strName); virtual void SetText(const wxString& strName);
virtual wxString GetLabel() const;
virtual void SetCheckable(bool checkable); virtual void SetCheckable(bool checkable);
virtual void Enable(bool bDoEnable = TRUE); virtual void Enable(bool bDoEnable = TRUE);
virtual void Check(bool bDoCheck = TRUE); virtual void Check(bool bDoCheck = TRUE);
virtual bool IsChecked() const; virtual bool IsChecked() const;
#if wxUSE_ACCEL
virtual wxAcceleratorEntry *GetAccel() const;
#endif // wxUSE_ACCEL
// unfortunately needed to resolve ambiguity between // unfortunately needed to resolve ambiguity between
// wxMenuItemBase::IsCheckable() and wxOwnerDrawn::IsCheckable() // wxMenuItemBase::IsCheckable() and wxOwnerDrawn::IsCheckable()
bool IsCheckable() const { return wxMenuItemBase::IsCheckable(); } bool IsCheckable() const { return wxMenuItemBase::IsCheckable(); }
@@ -60,9 +65,6 @@ public:
// menu handle depending on what we're // menu handle depending on what we're
int GetRealId() const; int GetRealId() const;
// delete the submenu
void DeleteSubMenu();
private: private:
DECLARE_DYNAMIC_CLASS(wxMenuItem) DECLARE_DYNAMIC_CLASS(wxMenuItem)
}; };

View File

@@ -400,6 +400,8 @@ void MyFrame::OnSize(wxSizeEvent& event)
wxSize size = event.GetSize(); wxSize size = event.GetSize();
Resize(size); Resize(size);
event.Skip();
} }
void MyFrame::Resize(const wxSize& size, const wxFont& font) void MyFrame::Resize(const wxSize& size, const wxFont& font)

482
samples/menu/menu.cpp Normal file
View File

@@ -0,0 +1,482 @@
/////////////////////////////////////////////////////////////////////////////
// Name: samples/menu.cpp
// Purpose: wxMenu/wxMenuBar sample
// Author: Vadim Zeitlin
// Modified by:
// Created: 01.11.99
// RCS-ID: $Id$
// Copyright: (c) 1999 Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include <wx/wx.h>
#include <wx/log.h>
#endif
// ----------------------------------------------------------------------------
// classes
// ----------------------------------------------------------------------------
// Define a new application
class MyApp: public wxApp
{
public:
bool OnInit();
};
// Define a new frame
class MyFrame: public wxFrame
{
public:
MyFrame();
virtual ~MyFrame() { delete m_menu; }
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnDummy(wxCommandEvent& event);
void OnAppendMenuItem(wxCommandEvent& event);
void OnAppendSubMenu(wxCommandEvent& event);
void OnDeleteMenuItem(wxCommandEvent& event);
void OnInsertMenuItem(wxCommandEvent& event);
void OnCheckMenuItem(wxCommandEvent& event);
void OnEnableMenuItem(wxCommandEvent& event);
void OnGetLabelMenuItem(wxCommandEvent& event);
void OnSetLabelMenuItem(wxCommandEvent& event);
void OnAppendMenu(wxCommandEvent& event);
void OnDeleteMenu(wxCommandEvent& event);
void OnToggleMenu(wxCommandEvent& event);
void OnEnableMenu(wxCommandEvent& event);
void OnGetLabelMenu(wxCommandEvent& event);
void OnSetLabelMenu(wxCommandEvent& event);
void OnRightDown(wxMouseEvent& event);
void OnUpdateCheckMenuItemUI(wxUpdateUIEvent& event);
private:
wxMenu *CreateDummyMenu();
wxMenuItem *GetLastMenuItem() const;
wxMenu *m_menu;
DECLARE_EVENT_TABLE()
};
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
enum
{
Menu_File_Quit = 100,
Menu_MenuBar_Toggle = 200,
Menu_MenuBar_Append,
Menu_MenuBar_Delete,
Menu_MenuBar_Enable,
Menu_MenuBar_GetLabel,
Menu_MenuBar_SetLabel,
Menu_Menu_Append = 300,
Menu_Menu_AppendSub,
Menu_Menu_Insert,
Menu_Menu_Delete,
Menu_Menu_Enable,
Menu_Menu_Check,
Menu_Menu_GetLabel,
Menu_Menu_SetLabel,
Menu_Dummy_First = 400,
Menu_Dummy_Second,
Menu_Dummy_Third,
Menu_Dummy_Fourth,
Menu_Dummy_Last,
Menu_Help_About = 1000,
Menu_Popup_ToBeDeleted = 2000,
Menu_Popup_ToBeGreyed,
Menu_Popup_ToBeChecked,
Menu_Popup_Submenu,
Menu_Max
};
// ----------------------------------------------------------------------------
// event tables
// ----------------------------------------------------------------------------
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(Menu_File_Quit, MyFrame::OnQuit)
EVT_MENU(Menu_Help_About, MyFrame::OnAbout)
EVT_MENU(Menu_MenuBar_Toggle, MyFrame::OnToggleMenu)
EVT_MENU(Menu_MenuBar_Append, MyFrame::OnAppendMenu)
EVT_MENU(Menu_MenuBar_Delete, MyFrame::OnDeleteMenu)
EVT_MENU(Menu_MenuBar_Enable, MyFrame::OnEnableMenu)
EVT_MENU(Menu_MenuBar_GetLabel, MyFrame::OnGetLabelMenu)
EVT_MENU(Menu_MenuBar_SetLabel, MyFrame::OnSetLabelMenu)
EVT_MENU(Menu_Menu_Append, MyFrame::OnAppendMenuItem)
EVT_MENU(Menu_Menu_AppendSub, MyFrame::OnAppendSubMenu)
EVT_MENU(Menu_Menu_Insert, MyFrame::OnInsertMenuItem)
EVT_MENU(Menu_Menu_Delete, MyFrame::OnDeleteMenuItem)
EVT_MENU(Menu_Menu_Enable, MyFrame::OnEnableMenuItem)
EVT_MENU(Menu_Menu_Check, MyFrame::OnCheckMenuItem)
EVT_MENU(Menu_Menu_GetLabel, MyFrame::OnGetLabelMenuItem)
EVT_MENU(Menu_Menu_SetLabel, MyFrame::OnSetLabelMenuItem)
EVT_MENU_RANGE(Menu_Dummy_First, Menu_Dummy_Last, MyFrame::OnDummy)
EVT_UPDATE_UI(Menu_Menu_Check, MyFrame::OnUpdateCheckMenuItemUI)
EVT_RIGHT_DOWN(MyFrame::OnRightDown)
END_EVENT_TABLE()
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// MyApp
// ----------------------------------------------------------------------------
IMPLEMENT_APP(MyApp)
// The `main program' equivalent, creating the windows and returning the
// main frame
bool MyApp::OnInit()
{
// Create the main frame window
MyFrame* frame = new MyFrame;
frame->Show(TRUE);
frame->SetStatusText("Hello, wxWindows");
SetTopWindow(frame);
return TRUE;
}
// ----------------------------------------------------------------------------
// MyFrame
// ----------------------------------------------------------------------------
// Define my frame constructor
MyFrame::MyFrame()
: wxFrame((wxFrame *)NULL, -1, "wxWindows menu sample",
wxDefaultPosition, wxSize(300, 200))
{
m_menu = NULL;
CreateStatusBar();
// create the menubar
wxMenu *fileMenu = new wxMenu;
fileMenu->Append(Menu_File_Quit, "E&xit\tAlt-X", "Quit toolbar sample" );
wxMenu *menubarMenu = new wxMenu;
menubarMenu->Append(Menu_MenuBar_Append, "&Append menu\tCtrl-A",
"Append a menu to the menubar");
menubarMenu->Append(Menu_MenuBar_Delete, "&Delete menu\tCtrl-D",
"Delete the last menu from the menubar");
menubarMenu->Append(Menu_MenuBar_Toggle, "&Toggle menu\tCtrl-T",
"Toggle the first menu in the menubar", TRUE);
menubarMenu->AppendSeparator();
menubarMenu->Append(Menu_MenuBar_Enable, "&Enable menu\tCtrl-E",
"Enable or disable the last menu", TRUE);
menubarMenu->AppendSeparator();
menubarMenu->Append(Menu_MenuBar_GetLabel, "&Get menu label\tCtrl-G",
"Get the label of the last menu");
menubarMenu->Append(Menu_MenuBar_SetLabel, "&Set menu label\tCtrl-S",
"Change the label of the last menu");
wxMenu *menuMenu = new wxMenu;
menuMenu->Append(Menu_Menu_Append, "&Append menu item\tAlt-A",
"Append a menu item to the last menu");
menuMenu->Append(Menu_Menu_AppendSub, "&Append sub menu\tAlt-S",
"Append a sub menu to the last menu");
menuMenu->Append(Menu_Menu_Insert, "&Insert menu item\tAlt-I",
"Insert a menu item in head of the last menu");
menuMenu->Append(Menu_Menu_Delete, "&Delete menu item\tAlt-D",
"Delete the last menu item from the last menu");
menuMenu->AppendSeparator();
menuMenu->Append(Menu_Menu_Enable, "&Enable menu item\tAlt-E",
"Enable or disable the last menu item", TRUE);
menuMenu->Append(Menu_Menu_Check, "&Check menu item\tAlt-C",
"Check or uncheck the last menu item", TRUE);
menuMenu->AppendSeparator();
menuMenu->Append(Menu_Menu_GetLabel, "&Get menu item label\tAlt-G",
"Get the label of the last menu item");
menuMenu->Append(Menu_Menu_SetLabel, "&Set menu item label\tAlt-S",
"Change the label of the last menu item");
wxMenu *helpMenu = new wxMenu;
helpMenu->Append(Menu_Help_About, "&About\tF1", "About menu sample");
wxMenuBar* menuBar = new wxMenuBar( wxMB_DOCKABLE );
menuBar->Append(fileMenu, "&File");
menuBar->Append(menubarMenu, "Menu&bar");
menuBar->Append(menuMenu, "&Menu");
menuBar->Append(helpMenu, "&Help");
// these items should be initially checked
menuBar->Check(Menu_MenuBar_Toggle, TRUE);
menuBar->Check(Menu_MenuBar_Enable, TRUE);
menuBar->Check(Menu_Menu_Enable, TRUE);
menuBar->Check(Menu_Menu_Check, FALSE);
// associate the menu bar with the frame
SetMenuBar(menuBar);
}
wxMenu *MyFrame::CreateDummyMenu()
{
wxMenu *menu = new wxMenu;
menu->Append(Menu_Dummy_First, "First item\tCtrl-F1");
menu->AppendSeparator();
menu->Append(Menu_Dummy_Second, "Second item\tCtrl-F2", "", TRUE);
return menu;
}
wxMenuItem *MyFrame::GetLastMenuItem() const
{
wxMenuBar *menubar = GetMenuBar();
wxMenu *menu = menubar->GetMenu(menubar->GetMenuCount() - 1);
wxMenuItemList::Node *node = menu->GetMenuItems().GetLast();
if ( !node )
{
wxLogWarning("No last item in the last menu!");
return NULL;
}
else
{
return node->GetData();
}
}
void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
Close(TRUE);
}
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
(void)wxMessageBox("wxWindows toolbar sample",
"About wxWindows menu sample",
wxICON_INFORMATION);
}
void MyFrame::OnDeleteMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *mbar = GetMenuBar();
size_t count = mbar->GetMenuCount();
if ( count == 2 )
{
// don't let delete the first 2 menus
wxLogError("Can't delete any more menus");
}
else
{
delete mbar->Remove(count - 1);
}
}
void MyFrame::OnAppendMenu(wxCommandEvent& WXUNUSED(event))
{
static s_count = 0;
wxString title;
title.Printf("Dummy menu &%d", ++s_count);
GetMenuBar()->Append(CreateDummyMenu(), title);
}
void MyFrame::OnToggleMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *mbar = GetMenuBar();
if ( !m_menu )
{
// hide the menu
m_menu = mbar->Remove(0);
}
else
{
// restore it
mbar->Insert(0, m_menu, "&File");
m_menu = NULL;
}
}
void MyFrame::OnEnableMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *mbar = GetMenuBar();
size_t count = mbar->GetMenuCount();
static bool s_enabled = TRUE;
s_enabled = !s_enabled;
mbar->EnableTop(count - 1, s_enabled);
}
void MyFrame::OnGetLabelMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *mbar = GetMenuBar();
size_t count = mbar->GetMenuCount();
wxLogMessage("The label of the last menu item is '%s'",
mbar->GetLabelTop(count - 1));
}
void MyFrame::OnSetLabelMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *mbar = GetMenuBar();
size_t count = mbar->GetMenuCount();
mbar->SetLabelTop(count - 1, "Dummy label &0");
}
void MyFrame::OnDummy(wxCommandEvent& event)
{
wxString s;
s.Printf("Dummy item #%d", event.GetId() - Menu_Dummy_First + 1);
wxMessageBox(s, "Menu sample", wxICON_INFORMATION);
}
void MyFrame::OnAppendMenuItem(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *menubar = GetMenuBar();
wxMenu *menu = menubar->GetMenu(menubar->GetMenuCount() - 1);
menu->AppendSeparator();
menu->Append(Menu_Dummy_Third, "Third dummy item\tCtrl-F3",
"Checkable item", TRUE);
}
void MyFrame::OnAppendSubMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *menubar = GetMenuBar();
wxMenu *menu = menubar->GetMenu(menubar->GetMenuCount() - 1);
menu->Append(Menu_Dummy_Last, "Dummy sub menu\tCtrl-F12",
CreateDummyMenu());
}
void MyFrame::OnDeleteMenuItem(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *menubar = GetMenuBar();
wxMenu *menu = menubar->GetMenu(menubar->GetMenuCount() - 1);
size_t count = menu->GetMenuItemCount();
if ( !count )
{
wxLogWarning("No items to delete!");
}
else
{
menu->Destroy(menu->GetMenuItems().Item(count - 1)->GetData());
}
}
void MyFrame::OnInsertMenuItem(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *menubar = GetMenuBar();
wxMenu *menu = menubar->GetMenu(menubar->GetMenuCount() - 1);
menu->Insert(0, wxMenuItem::New(menu, Menu_Dummy_Fourth,
"Fourth dummy item\tCtrl-F4"));
menu->Insert(1, wxMenuItem::New(menu, wxID_SEPARATOR, ""));
}
void MyFrame::OnEnableMenuItem(wxCommandEvent& WXUNUSED(event))
{
wxMenuItem *item = GetLastMenuItem();
if ( item )
{
item->Enable(!item->IsEnabled());
}
}
void MyFrame::OnCheckMenuItem(wxCommandEvent& WXUNUSED(event))
{
wxMenuItem *item = GetLastMenuItem();
item->Toggle();
}
void MyFrame::OnUpdateCheckMenuItemUI(wxUpdateUIEvent& event)
{
wxMenuItem *item = GetLastMenuItem();
event.Enable(item && item->IsCheckable());
}
void MyFrame::OnGetLabelMenuItem(wxCommandEvent& WXUNUSED(event))
{
wxMenuItem *item = GetLastMenuItem();
if ( item )
{
wxLogMessage("The label of the last menu item is '%s'",
item->GetLabel());
}
}
void MyFrame::OnSetLabelMenuItem(wxCommandEvent& WXUNUSED(event))
{
wxMenuItem *item = GetLastMenuItem();
if ( item )
{
item->SetText("Dummy menu item text");
}
}
void MyFrame::OnRightDown(wxMouseEvent &event )
{
wxMenu menu("Test popup");
menu.Append(Menu_Help_About, "&About");
menu.Append(Menu_Popup_Submenu, "Submenu", CreateDummyMenu());
menu.Append(Menu_Popup_ToBeDeleted, "To be deleted");
menu.Append(Menu_Popup_ToBeChecked, "To be checked", "", TRUE);
menu.Append(Menu_Popup_ToBeGreyed, "To be greyed");
menu.AppendSeparator();
menu.Append(Menu_File_Quit, "E&xit");
menu.Delete(Menu_Popup_ToBeDeleted);
menu.Check(Menu_Popup_ToBeChecked, TRUE);
menu.Enable(Menu_Popup_ToBeGreyed, FALSE);
PopupMenu( &menu, event.GetX(), event.GetY() );
}

View File

@@ -71,8 +71,6 @@ public:
const wxSize& size = wxDefaultSize, const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE); long style = wxDEFAULT_FRAME_STYLE);
virtual ~MyFrame() { delete m_menu; }
void OnQuit(wxCommandEvent& event); void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event); void OnAbout(wxCommandEvent& event);
@@ -94,8 +92,6 @@ private:
bool m_smallToolbar; bool m_smallToolbar;
wxTextCtrl* m_textWindow; wxTextCtrl* m_textWindow;
wxMenu *m_menu;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
@@ -109,10 +105,7 @@ enum
{ {
IDM_TOOLBAR_TOGGLETOOLBAR = 200, IDM_TOOLBAR_TOGGLETOOLBAR = 200,
IDM_TOOLBAR_ENABLEPRINT, IDM_TOOLBAR_ENABLEPRINT,
IDM_TOOLBAR_TOGGLEHELP, IDM_TOOLBAR_TOGGLEHELP
IDM_MENU_TOGGLE,
IDM_MENU_APPEND,
IDM_MENU_DELETE
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -130,10 +123,6 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(IDM_TOOLBAR_ENABLEPRINT, MyFrame::OnEnablePrint) EVT_MENU(IDM_TOOLBAR_ENABLEPRINT, MyFrame::OnEnablePrint)
EVT_MENU(IDM_TOOLBAR_TOGGLEHELP, MyFrame::OnToggleHelp) EVT_MENU(IDM_TOOLBAR_TOGGLEHELP, MyFrame::OnToggleHelp)
EVT_MENU(IDM_MENU_TOGGLE, MyFrame::OnToggleMenu)
EVT_MENU(IDM_MENU_APPEND, MyFrame::OnAppendMenu)
EVT_MENU(IDM_MENU_DELETE, MyFrame::OnDeleteMenu)
EVT_MENU(-1, MyFrame::OnToolLeftClick) EVT_MENU(-1, MyFrame::OnToolLeftClick)
EVT_TOOL_ENTER(ID_TOOLBAR, MyFrame::OnToolEnter) EVT_TOOL_ENTER(ID_TOOLBAR, MyFrame::OnToolEnter)
@@ -261,7 +250,6 @@ MyFrame::MyFrame(wxFrame* parent,
long style) long style)
: wxFrame(parent, id, title, pos, size, style) : wxFrame(parent, id, title, pos, size, style)
{ {
m_menu = NULL;
m_textWindow = new wxTextCtrl(this, -1, "", wxPoint(0, 0), wxSize(-1, -1), wxTE_MULTILINE); m_textWindow = new wxTextCtrl(this, -1, "", wxPoint(0, 0), wxSize(-1, -1), wxTE_MULTILINE);
m_smallToolbar = FALSE; m_smallToolbar = FALSE;
@@ -280,11 +268,6 @@ MyFrame::MyFrame(wxFrame* parent,
wxMenu *fileMenu = new wxMenu; wxMenu *fileMenu = new wxMenu;
fileMenu->Append(wxID_EXIT, "E&xit", "Quit toolbar sample" ); fileMenu->Append(wxID_EXIT, "E&xit", "Quit toolbar sample" );
wxMenu *menuMenu = new wxMenu;
menuMenu->Append(IDM_MENU_APPEND, "&Append menu");
menuMenu->Append(IDM_MENU_DELETE, "&Delete menu");
menuMenu->Append(IDM_MENU_TOGGLE, "&Toggle menu", "", TRUE);
wxMenu *helpMenu = new wxMenu; wxMenu *helpMenu = new wxMenu;
helpMenu->Append(wxID_HELP, "&About", "About toolbar sample"); helpMenu->Append(wxID_HELP, "&About", "About toolbar sample");
@@ -292,7 +275,6 @@ MyFrame::MyFrame(wxFrame* parent,
menuBar->Append(fileMenu, "&File"); menuBar->Append(fileMenu, "&File");
menuBar->Append(tbarMenu, "&Toolbar"); menuBar->Append(tbarMenu, "&Toolbar");
menuBar->Append(menuMenu, "&Menubar");
menuBar->Append(helpMenu, "&Help"); menuBar->Append(helpMenu, "&Help");
// Associate the menu bar with the frame // Associate the menu bar with the frame
@@ -333,53 +315,6 @@ void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
(void)wxMessageBox("wxWindows toolbar sample", "About wxToolBar"); (void)wxMessageBox("wxWindows toolbar sample", "About wxToolBar");
} }
void MyFrame::OnDeleteMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *mbar = GetMenuBar();
size_t count = mbar->GetMenuCount();
if ( count == 3 )
{
// don't let delete the first 3 menus
wxLogError("Can't delete any more menus");
}
else
{
delete mbar->Remove(count - 1);
}
}
void MyFrame::OnAppendMenu(wxCommandEvent& WXUNUSED(event))
{
static s_count = 0;
wxMenu *menu = new wxMenu;
menu->Append(0, "First item");
menu->AppendSeparator();
menu->Append(0, "Second item");
wxString title;
title.Printf("Dummy menu &%d", ++s_count);
GetMenuBar()->Append(menu, title);
}
void MyFrame::OnToggleMenu(wxCommandEvent& WXUNUSED(event))
{
wxMenuBar *mbar = GetMenuBar();
if ( !m_menu )
{
// hide the menu
m_menu = mbar->Remove(1);
}
else
{
// restore it
mbar->Insert(1, m_menu, "&Toolbar");
m_menu = NULL;
}
}
void MyFrame::OnToolLeftClick(wxCommandEvent& event) void MyFrame::OnToolLeftClick(wxCommandEvent& event)
{ {
wxString str; wxString str;

View File

@@ -1931,11 +1931,21 @@ void wxFileHistory::RemoveFileFromHistory(int i)
// delete the last menu item which is unused now // delete the last menu item which is unused now
menu->Delete(wxID_FILE1 + m_fileHistoryN - 1); menu->Delete(wxID_FILE1 + m_fileHistoryN - 1);
// unfortunately, we can't delete separator (there is no function to // delete the last separator too if no more files are left
// delete item by position, only by id - and what if there are several if ( m_fileHistoryN == 1 )
// separators in this menu?) - so we will be always left with at least {
// one and, even worse, we will add another one if this was the last wxMenuItemList::Node *node = menu->GetMenuItems().GetLast();
// file... (FIXME) if ( node )
{
wxMenuItem *menuItem = node->GetData();
if ( menuItem->IsSeparator() )
{
menu->Delete(menuItem);
}
//else: should we search backwards for the last separator?
}
//else: menu is empty somehow
}
} }
m_fileHistoryN--; m_fileHistoryN--;

View File

@@ -37,14 +37,410 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#include "wx/listimpl.cpp" #include "wx/listimpl.cpp"
WX_DEFINE_LIST(wxMenuList); WX_DEFINE_LIST(wxMenuList);
WX_DEFINE_LIST(wxMenuItemList);
// ============================================================================ // ============================================================================
// implementation // implementation
// ============================================================================ // ============================================================================
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ctor and dtor // wxMenuItem
// ----------------------------------------------------------------------------
wxMenuItemBase::~wxMenuItemBase()
{
delete m_subMenu;
}
#if wxUSE_ACCEL
void wxMenuItemBase::SetAccel(wxAcceleratorEntry *accel)
{
wxString text = m_text.BeforeFirst(wxT('\t'));
if ( accel )
{
text += wxT('\t');
int flags = accel->GetFlags();
if ( flags & wxACCEL_ALT )
text += wxT("Alt-");
if ( flags & wxACCEL_CTRL )
text += wxT("Ctrl-");
if ( flags & wxACCEL_SHIFT )
text += wxT("Shift-");
int code = accel->GetKeyCode();
switch ( code )
{
case WXK_F1:
case WXK_F2:
case WXK_F3:
case WXK_F4:
case WXK_F5:
case WXK_F6:
case WXK_F7:
case WXK_F8:
case WXK_F9:
case WXK_F10:
case WXK_F11:
case WXK_F12:
text << wxT('F') << code - WXK_F1 + 1;
break;
// if there are any other keys wxGetAccelFromString() may return,
// we should process them here
default:
if ( wxIsalnum(code) )
{
text << (wxChar)code;
break;
}
wxFAIL_MSG( wxT("unknown keyboard accel") );
}
}
SetText(text);
}
#endif // wxUSE_ACCEL
// ----------------------------------------------------------------------------
// wxMenu ctor and dtor
// ----------------------------------------------------------------------------
void wxMenuBase::Init(long style)
{
m_items.DeleteContents(TRUE);
m_menuBar = (wxMenuBar *)NULL;
m_menuParent = (wxMenu *)NULL;
m_invokingWindow = (wxWindow *)NULL;
m_style = style;
m_clientData = (void *)NULL;
m_eventHandler = this;
}
wxMenuBase::~wxMenuBase()
{
// nothing to do, wxMenuItemList dtor will delete the menu items
}
// ----------------------------------------------------------------------------
// wxMenu item adding/removing
// ----------------------------------------------------------------------------
bool wxMenuBase::DoAppend(wxMenuItem *item)
{
wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Append()") );
m_items.Append(item);
return TRUE;
}
bool wxMenuBase::Insert(size_t pos, wxMenuItem *item)
{
wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Insert") );
wxCHECK_MSG( pos < GetMenuItemCount(), FALSE,
wxT("invalid index in wxMenu::Insert") );
return DoInsert(pos, item);
}
bool wxMenuBase::DoInsert(size_t pos, wxMenuItem *item)
{
wxCHECK_MSG( item, FALSE, wxT("invalid item in wxMenu::Insert()") );
wxMenuItemList::Node *node = m_items.Item(pos);
wxCHECK_MSG( node, FALSE, wxT("invalid index in wxMenu::Insert()") );
m_items.Insert(node, item);
return TRUE;
}
wxMenuItem *wxMenuBase::Remove(wxMenuItem *item)
{
wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Remove") );
return DoRemove(item);
}
wxMenuItem *wxMenuBase::DoRemove(wxMenuItem *item)
{
wxMenuItemList::Node *node = m_items.Find(item);
// if we get here, the item is valid or one of Remove() functions is broken
wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
// we detach the item, but we do delete the list node (i.e. don't call
// DetachNode() here!)
node->SetData((wxMenuItem *)NULL); // to prevent it from deleting the item
m_items.DeleteNode(node);
// item isn't attached to anything any more
wxMenu *submenu = item->GetSubMenu();
if ( submenu )
{
submenu->SetParent((wxMenu *)NULL);
}
return item;
}
bool wxMenuBase::Delete(wxMenuItem *item)
{
wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Delete") );
return DoDelete(item);
}
bool wxMenuBase::DoDelete(wxMenuItem *item)
{
wxMenuItem *item2 = DoRemove(item);
wxCHECK_MSG( item2, FALSE, wxT("failed to delete menu item") );
// don't delete the submenu
item2->SetSubMenu((wxMenu *)NULL);
delete item2;
return TRUE;
}
bool wxMenuBase::Destroy(wxMenuItem *item)
{
wxCHECK_MSG( item, NULL, wxT("invalid item in wxMenu::Destroy") );
return DoDestroy(item);
}
bool wxMenuBase::DoDestroy(wxMenuItem *item)
{
wxMenuItem *item2 = DoRemove(item);
wxCHECK_MSG( item2, FALSE, wxT("failed to delete menu item") );
delete item2;
return TRUE;
}
// ----------------------------------------------------------------------------
// wxMenu searching for items
// ----------------------------------------------------------------------------
// Finds the item id matching the given string, -1 if not found.
int wxMenuBase::FindItem(const wxString& text) const
{
wxString label = wxMenuItem(NULL, wxID_SEPARATOR, text).GetLabel();
for ( wxMenuItemList::Node *node = m_items.GetFirst();
node;
node = node->GetNext() )
{
wxMenuItem *item = node->GetData();
if ( item->IsSubMenu() )
{
int rc = item->GetSubMenu()->FindItem(label);
if ( rc != wxNOT_FOUND )
return rc;
}
else if ( !item->IsSeparator() )
{
if ( item->GetLabel() == label )
return item->GetId();
}
}
return wxNOT_FOUND;
}
// recursive search for item by id
wxMenuItem *wxMenuBase::FindItem(int itemId, wxMenu **itemMenu) const
{
if ( itemMenu )
*itemMenu = NULL;
wxMenuItem *item = NULL;
for ( wxMenuItemList::Node *node = m_items.GetFirst();
node && !item;
node = node->GetNext() )
{
item = node->GetData();
if ( item->GetId() == itemId )
{
if ( itemMenu )
*itemMenu = (wxMenu *)this;
}
else if ( item->IsSubMenu() )
{
item = item->GetSubMenu()->FindItem(itemId, itemMenu);
}
else
{
// don't exit the loop
item = NULL;
}
}
return item;
}
// non recursive search
wxMenuItem *wxMenuBase::FindChildItem(int id, size_t *ppos) const
{
wxMenuItem *item = (wxMenuItem *)NULL;
wxMenuItemList::Node *node = GetMenuItems().GetFirst();
size_t pos;
for ( pos = 0; node; pos++ )
{
item = node->GetData();
if ( item->GetId() == id )
break;
node = node->GetNext();
}
if ( ppos )
{
*ppos = item ? pos : wxNOT_FOUND;
}
return item;
}
// ----------------------------------------------------------------------------
// wxMenu helpers
// ----------------------------------------------------------------------------
// Update a menu and all submenus recursively. source is the object that has
// the update event handlers defined for it. If NULL, the menu or associated
// window will be used.
void wxMenuBase::UpdateUI(wxEvtHandler* source)
{
if ( !source && GetInvokingWindow() )
source = GetInvokingWindow()->GetEventHandler();
if ( !source )
source = GetEventHandler();
if ( !source )
source = this;
wxMenuItemList::Node* node = GetMenuItems().GetFirst();
while ( node )
{
wxMenuItem* item = node->GetData();
if ( !item->IsSeparator() )
{
wxWindowID id = item->GetId();
wxUpdateUIEvent event(id);
event.SetEventObject( source );
if ( source->ProcessEvent(event) )
{
// if anything changed, update the chanegd attribute
if (event.GetSetText())
SetLabel(id, event.GetText());
if (event.GetSetChecked())
Check(id, event.GetChecked());
if (event.GetSetEnabled())
Enable(id, event.GetEnabled());
}
// recurse to the submenus
if ( item->GetSubMenu() )
item->GetSubMenu()->UpdateUI(source);
}
//else: item is a separator (which don't process update UI events)
node = node->GetNext();
}
}
// ----------------------------------------------------------------------------
// wxMenu functions forwarded to wxMenuItem
// ----------------------------------------------------------------------------
void wxMenuBase::Enable( int id, bool enable )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
item->Enable(enable);
}
bool wxMenuBase::IsEnabled( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsEnabled: no such item") );
return item->IsEnabled();
}
void wxMenuBase::Check( int id, bool enable )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
item->Check(enable);
}
bool wxMenuBase::IsChecked( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsChecked: no such item") );
return item->IsChecked();
}
void wxMenuBase::SetLabel( int id, const wxString &label )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
item->SetText(label);
}
wxString wxMenuBase::GetLabel( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetLabel: no such item") );
return item->GetText();
}
void wxMenuBase::SetHelpString( int id, const wxString& helpString )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
item->SetHelp( helpString );
}
wxString wxMenuBase::GetHelpString( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetHelpString: no such item") );
return item->GetHelp();
}
// ----------------------------------------------------------------------------
// wxMenuBarBase ctor and dtor
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxMenuBarBase::wxMenuBarBase() wxMenuBarBase::wxMenuBarBase()

View File

@@ -2890,7 +2890,7 @@ bool wxWindowBase::LoadFromResource(wxWindow *parent, const wxString& resourceNa
else if (IsKindOf(CLASSINFO(wxPanel))) else if (IsKindOf(CLASSINFO(wxPanel)))
{ {
wxPanel* panel = (wxPanel *)this; wxPanel* panel = (wxPanel *)this;
if (!panel->Create(parent, -1, wxPoint(x, y), wxSize(width, height), theWindowStyle, name)) if (!panel->Create(parent, -1, wxPoint(x, y), wxSize(width, height), theWindowStyle | wxTAB_TRAVERSAL, name))
return FALSE; return FALSE;
} }
else else

View File

@@ -31,6 +31,10 @@
extern void wxapp_install_idle_handler(); extern void wxapp_install_idle_handler();
extern bool g_isIdle; extern bool g_isIdle;
#if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL
static wxString GetHotKey( const wxMenuItem& item );
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxMenuBar // wxMenuBar
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -355,7 +359,7 @@ int wxMenuBar::FindMenuItem( const wxString &menuString, const wxString &itemStr
// Find a wxMenuItem using its id. Recurses down into sub-menus // Find a wxMenuItem using its id. Recurses down into sub-menus
static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id) static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id)
{ {
wxMenuItem* result = menu->FindItem(id); wxMenuItem* result = menu->FindChildItem(id);
wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
while ( node && result == NULL ) while ( node && result == NULL )
@@ -440,7 +444,7 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
if (!menu->IsEnabled(id)) if (!menu->IsEnabled(id))
return; return;
wxMenuItem* item = menu->FindItem( id ); wxMenuItem* item = menu->FindChildItem( id );
wxCHECK_RET( item, wxT("error in menu item callback") ); wxCHECK_RET( item, wxT("error in menu item callback") );
if (item->IsCheckable()) if (item->IsCheckable())
@@ -569,6 +573,28 @@ wxMenuItem::~wxMenuItem()
// don't delete menu items, the menus take care of that // don't delete menu items, the menus take care of that
} }
// return the menu item text without any menu accels
wxString wxMenuItem::GetLabel() const
{
wxString label;
#if (GTK_MINOR_VERSION > 0)
for ( const wxChar *pc = m_text.c_str(); *pc; pc++ )
{
if ( *pc == wxT('_') )
{
// this is the escape character for GTK+ - skip it
continue;
}
label += *pc;
}
#else // GTK+ 1.0
label = m_text;
#endif // GTK+ 1.2/1.0
return label;
}
void wxMenuItem::SetText( const wxString& str ) void wxMenuItem::SetText( const wxString& str )
{ {
DoSetText(str); DoSetText(str);
@@ -623,6 +649,25 @@ void wxMenuItem::DoSetText( const wxString& str )
#endif #endif
} }
#if wxUSE_ACCEL
wxAcceleratorEntry *wxMenuItem::GetAccel() const
{
if ( !item.GetHotKey() )
{
// nothing
return (wxAcceleratorEntry *)NULL;
}
// as wxGetAccelFromString() looks for TAB, insert a dummy one here
wxString label;
label << wxT('\t') << item.GetHotKey();
return wxGetAccelFromString(label);
}
#endif // wxUSE_ACCEL
void wxMenuItem::Check( bool check ) void wxMenuItem::Check( bool check )
{ {
wxCHECK_RET( m_menuItem, wxT("invalid menu item") ); wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
@@ -658,11 +703,7 @@ wxString wxMenuItem::GetFactoryPath() const
{ {
/* in order to get the pointer to the item we need the item text _without_ underscores */ /* in order to get the pointer to the item we need the item text _without_ underscores */
wxString path( wxT("<main>/") ); wxString path( wxT("<main>/") );
for ( const wxChar *pc = m_text; *pc != wxT('\0'); pc++ ) path += GetLabel();
{
while (*pc == wxT('_')) pc++; /* skip it */
path << *pc;
}
return path; return path;
} }
@@ -673,17 +714,8 @@ wxString wxMenuItem::GetFactoryPath() const
IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler) IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler)
void void wxMenu::Init()
wxMenu::Init( const wxString& title,
long style,
const wxFunction func
)
{ {
m_title = title;
m_items.DeleteContents( TRUE );
m_invokingWindow = (wxWindow *) NULL;
m_style = style;
#if (GTK_MINOR_VERSION > 0) #if (GTK_MINOR_VERSION > 0)
m_accel = gtk_accel_group_new(); m_accel = gtk_accel_group_new();
m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "<main>", m_accel ); m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "<main>", m_accel );
@@ -692,18 +724,6 @@ wxMenu::Init( const wxString& title,
m_menu = gtk_menu_new(); // Do not show! m_menu = gtk_menu_new(); // Do not show!
#endif #endif
m_callback = func;
m_eventHandler = this;
m_clientData = (void*) NULL;
if (m_title.IsNull()) m_title = wxT("");
if (m_title != wxT(""))
{
Append(-2, m_title);
AppendSeparator();
}
m_owner = (GtkWidget*) NULL; m_owner = (GtkWidget*) NULL;
#if (GTK_MINOR_VERSION > 0) #if (GTK_MINOR_VERSION > 0)
@@ -722,40 +742,30 @@ wxMenu::Init( const wxString& title,
//GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" ); //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
} }
#endif #endif
// append the title as the very first entry if we have it
if ( !!m_title )
{
Append(-2, m_title);
AppendSeparator();
}
} }
wxMenu::~wxMenu() wxMenu::~wxMenu()
{ {
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
wxMenu *submenu = item->GetSubMenu();
if (submenu)
delete submenu;
node = node->Next();
}
gtk_widget_destroy( m_menu ); gtk_widget_destroy( m_menu );
gtk_object_unref( GTK_OBJECT(m_factory) ); gtk_object_unref( GTK_OBJECT(m_factory) );
// the menu items are deleted by the base class dtor
} }
void wxMenu::SetTitle( const wxString& title ) virtual bool wxMenu::DoAppend(wxMenuItem *mitem)
{ {
// TODO Waiting for something better GtkWidget *menuItem;
m_title = title;
}
const wxString wxMenu::GetTitle() const
{
return m_title;
}
void wxMenu::AppendSeparator()
{
wxMenuItem *mitem = new wxMenuItem(this, wxID_SEPARATOR);
if ( mitem->IsSeparator() )
{
#if (GTK_MINOR_VERSION > 0) #if (GTK_MINOR_VERSION > 0)
GtkItemFactoryEntry entry; GtkItemFactoryEntry entry;
entry.path = "/sep"; entry.path = "/sep";
@@ -767,30 +777,191 @@ void wxMenu::AppendSeparator()
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */ gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
/* this will be wrong for more than one separator. do we care? */ /* this will be wrong for more than one separator. do we care? */
GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/sep" ); menuItem = gtk_item_factory_get_widget( m_factory, "<main>/sep" );
#else #else // GTK+ 1.0
GtkWidget *menuItem = gtk_menu_item_new(); menuItem = gtk_menu_item_new();
#endif // GTK 1.2/1.0
}
else if ( mitem->IsSubMenu() )
{
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) 0;
entry.callback_action = 0;
entry.item_type = "<Branch>";
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_item( m_factory, path.mb_str() );
#else // GTK+ 1.0
GtkWidget *menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str());
#endif // GTK 1.2/1.0
gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), subMenu->m_menu );
}
else // a normal item
{
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
entry.callback_action = 0;
if (checkable)
entry.item_type = "<CheckItem>";
else
entry.item_type = "<Item>";
#if wxUSE_ACCEL
// due to an apparent bug in GTK+, we have to use a static buffer here -
// otherwise GTK+ 1.2.2 manages to override the memory we pass to it
// somehow! (VZ)
static char s_accel[32]; // must be big enough for <control><alt><shift>F12
strncpy(s_accel, GetHotKey(*mitem).mb_str(), WXSIZEOF(s_accel));
entry.accelerator = s_accel;
#else // !wxUSE_ACCEL
entry.accelerator = (char*) NULL;
#endif // wxUSE_ACCEL/!wxUSE_ACCEL
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, path.mb_str() );
#else // GTK+ 1.0
GtkWidget *menuItem = checkable ? gtk_check_menu_item_new_with_label( mitem->GetText().mb_str() )
: gtk_menu_item_new_with_label( mitem->GetText().mb_str() );
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer)this );
#endif // GTK+ 1.2/1.0
}
if ( !mitem->IsSeparator() )
{
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer)this );
}
#if GTK_MINOR_VERSION == 0
gtk_menu_append( GTK_MENU(m_menu), menuItem ); gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem ); gtk_widget_show( menuItem );
#endif #endif // GTK+ 1.0
mitem->SetMenuItem(menuItem); mitem->SetMenuItem(menuItem);
m_items.Append( mitem );
return wxMenuBase::DoAppend(mitem);
} }
// VZ: this seems to be GTK+ 1.0 only code, I don't understand why there were
// both specialized versions of Append() and this one before my changes,
// but it seems that the others are better...
#if 0
void wxMenu::Append( wxMenuItem *item )
{
GtkWidget *menuItem = (GtkWidget*) NULL;
if (item->IsSeparator())
menuItem = gtk_menu_item_new();
else if (item->IsSubMenu())
menuItem = gtk_menu_item_new_with_label(item->GetText().mbc_str());
else
menuItem = item->IsCheckable() ? gtk_check_menu_item_new_with_label(item->GetText().mbc_str())
: gtk_menu_item_new_with_label(item->GetText().mbc_str());
if (!item->IsSeparator())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer*)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer*)this );
if (!item->IsSubMenu())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer*)this );
}
}
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
item->SetMenuItem(menuItem);
}
#endif // 0
bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
{
if ( !wxMenuBase::DoInsert(pos, item) )
return FALSE;
wxFAIL_MSG(wxT("not implemented"));
return FALSE;
}
wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
{
if ( !wxMenuBase::DoRemove(item) )
return (wxMenuItem *)NULL;
// TODO: this code doesn't delete the item factory item and this seems
// impossible as of GTK 1.2.6.
gtk_widget_destroy( item->GetMenuItem() );
return item;
}
int wxMenu::FindMenuIdByMenuItem( GtkWidget *menuItem ) const
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetMenuItem() == menuItem)
return item->GetId();
node = node->Next();
}
return wxNOT_FOUND;
}
// ----------------------------------------------------------------------------
// helpers
// ----------------------------------------------------------------------------
#if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL #if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL
static wxString GetHotKey( const wxMenuItem& item ) static wxString GetHotKey( const wxMenuItem& item )
{ {
wxString hotkey; wxString hotkey;
// as wxGetAccelFromString() looks for TAB, insert a dummy one here wxAcceleratorEntry *accel = item.GetAccel();
wxString label;
label << wxT('\t') << item.GetHotKey();
// but if the hotkey is empty don't do anything
if ( label.length() > 1 )
{
wxAcceleratorEntry *accel = wxGetAccelFromString(label);
if ( accel ) if ( accel )
{ {
int flags = accel->GetFlags(); int flags = accel->GetFlags();
@@ -835,361 +1006,8 @@ static wxString GetHotKey( const wxMenuItem& item )
delete accel; delete accel;
} }
}
return hotkey; return hotkey;
} }
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool checkable )
{
wxMenuItem *mitem = new wxMenuItem(this, id, item, helpStr, checkable);
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
entry.callback_action = 0;
if (checkable)
entry.item_type = "<CheckItem>";
else
entry.item_type = "<Item>";
#if wxUSE_ACCEL
// due to an apparent bug in GTK+, we have to use a static buffer here -
// otherwise GTK+ 1.2.2 manages to override the memory we pass to it
// somehow! (VZ)
static char s_accel[32]; // must be big enough for <control><alt><shift>F12
strncpy(s_accel, GetHotKey(*mitem).mb_str(), WXSIZEOF(s_accel));
entry.accelerator = s_accel;
#else
entry.accelerator = (char*) NULL;
#endif
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, path.mb_str() );
#else
GtkWidget *menuItem = checkable ? gtk_check_menu_item_new_with_label( mitem->GetText().mb_str() )
: gtk_menu_item_new_with_label( mitem->GetText().mb_str() );
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer)this );
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
#endif
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer)this );
mitem->SetMenuItem(menuItem);
m_items.Append( mitem );
}
void wxMenu::Append( int id, const wxString &item, wxMenu *subMenu, const wxString &helpStr )
{
wxMenuItem *mitem = new wxMenuItem(this, id, item, helpStr, FALSE, subMenu);
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) 0;
entry.callback_action = 0;
entry.item_type = "<Branch>";
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_item( m_factory, path.mb_str() );
#else
GtkWidget *menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str());
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
#endif
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer*)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer*)this );
gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), subMenu->m_menu );
mitem->SetMenuItem(menuItem);
m_items.Append( mitem );
}
void wxMenu::Append( wxMenuItem *item )
{
m_items.Append( item );
GtkWidget *menuItem = (GtkWidget*) NULL;
if (item->IsSeparator())
menuItem = gtk_menu_item_new();
else if (item->IsSubMenu())
menuItem = gtk_menu_item_new_with_label(item->GetText().mbc_str());
else
menuItem = item->IsCheckable() ? gtk_check_menu_item_new_with_label(item->GetText().mbc_str())
: gtk_menu_item_new_with_label(item->GetText().mbc_str());
if (!item->IsSeparator())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer*)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer*)this );
if (!item->IsSubMenu())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer*)this );
}
}
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
item->SetMenuItem(menuItem);
}
void wxMenu::Delete( int id )
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetId() == id)
{
/* TODO: this code doesn't delete the item factory item and
this seems impossible as of GTK 1.2.6. */
gtk_widget_destroy( item->GetMenuItem() );
m_items.DeleteNode( node );
return;
}
node = node->Next();
}
}
int wxMenu::FindItem( const wxString itemString ) const
{
wxString s = wxT("");
for ( const wxChar *pc = itemString; *pc != wxT('\0'); pc++ )
{
if (*pc == wxT('&'))
{
pc++; /* skip it */
#if (GTK_MINOR_VERSION > 0)
s << wxT('_');
#endif
}
s << *pc;
}
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetText() == s)
{
return item->GetId();
}
node = node->Next();
}
return wxNOT_FOUND;
}
void wxMenu::Enable( int id, bool enable )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
item->Enable(enable);
}
bool wxMenu::IsEnabled( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsEnabled: no such item") );
return item->IsEnabled();
}
void wxMenu::Check( int id, bool enable )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
item->Check(enable);
}
bool wxMenu::IsChecked( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsChecked: no such item") );
return item->IsChecked();
}
void wxMenu::SetLabel( int id, const wxString &label )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
item->SetText(label);
}
wxString wxMenu::GetLabel( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetLabel: no such item") );
return item->GetText();
}
void wxMenu::SetHelpString( int id, const wxString& helpString )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
item->SetHelp( helpString );
}
wxString wxMenu::GetHelpString( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetHelpString: no such item") );
return item->GetHelp();
}
int wxMenu::FindMenuIdByMenuItem( GtkWidget *menuItem ) const
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetMenuItem() == menuItem)
return item->GetId();
node = node->Next();
}
return wxNOT_FOUND;
}
wxMenuItem *wxMenu::FindItem(int id) const
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetId() == id)
{
return item;
}
node = node->Next();
}
/* Not finding anything here can be correct
* when search the entire menu system for
* an entry -> no error message. */
return (wxMenuItem *) NULL;
}
void wxMenu::SetInvokingWindow( wxWindow *win )
{
m_invokingWindow = win;
}
wxWindow *wxMenu::GetInvokingWindow()
{
return m_invokingWindow;
}
// Update a menu and all submenus recursively. source is the object that has
// the update event handlers defined for it. If NULL, the menu or associated
// window will be used.
void wxMenu::UpdateUI(wxEvtHandler* source)
{
if (!source && GetInvokingWindow())
source = GetInvokingWindow()->GetEventHandler();
if (!source)
source = GetEventHandler();
if (!source)
source = this;
wxNode* node = GetItems().First();
while (node)
{
wxMenuItem* item = (wxMenuItem*) node->Data();
if ( !item->IsSeparator() )
{
wxWindowID id = item->GetId();
wxUpdateUIEvent event(id);
event.SetEventObject( source );
if (source->ProcessEvent(event))
{
if (event.GetSetText())
SetLabel(id, event.GetText());
if (event.GetSetChecked())
Check(id, event.GetChecked());
if (event.GetSetEnabled())
Enable(id, event.GetEnabled());
}
if (item->GetSubMenu())
item->GetSubMenu()->UpdateUI(source);
}
node = node->Next();
}
}

View File

@@ -31,6 +31,10 @@
extern void wxapp_install_idle_handler(); extern void wxapp_install_idle_handler();
extern bool g_isIdle; extern bool g_isIdle;
#if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL
static wxString GetHotKey( const wxMenuItem& item );
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// wxMenuBar // wxMenuBar
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -355,7 +359,7 @@ int wxMenuBar::FindMenuItem( const wxString &menuString, const wxString &itemStr
// Find a wxMenuItem using its id. Recurses down into sub-menus // Find a wxMenuItem using its id. Recurses down into sub-menus
static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id) static wxMenuItem* FindMenuItemByIdRecursive(const wxMenu* menu, int id)
{ {
wxMenuItem* result = menu->FindItem(id); wxMenuItem* result = menu->FindChildItem(id);
wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast wxNode *node = ((wxMenu *)menu)->GetItems().First(); // const_cast
while ( node && result == NULL ) while ( node && result == NULL )
@@ -440,7 +444,7 @@ static void gtk_menu_clicked_callback( GtkWidget *widget, wxMenu *menu )
if (!menu->IsEnabled(id)) if (!menu->IsEnabled(id))
return; return;
wxMenuItem* item = menu->FindItem( id ); wxMenuItem* item = menu->FindChildItem( id );
wxCHECK_RET( item, wxT("error in menu item callback") ); wxCHECK_RET( item, wxT("error in menu item callback") );
if (item->IsCheckable()) if (item->IsCheckable())
@@ -569,6 +573,28 @@ wxMenuItem::~wxMenuItem()
// don't delete menu items, the menus take care of that // don't delete menu items, the menus take care of that
} }
// return the menu item text without any menu accels
wxString wxMenuItem::GetLabel() const
{
wxString label;
#if (GTK_MINOR_VERSION > 0)
for ( const wxChar *pc = m_text.c_str(); *pc; pc++ )
{
if ( *pc == wxT('_') )
{
// this is the escape character for GTK+ - skip it
continue;
}
label += *pc;
}
#else // GTK+ 1.0
label = m_text;
#endif // GTK+ 1.2/1.0
return label;
}
void wxMenuItem::SetText( const wxString& str ) void wxMenuItem::SetText( const wxString& str )
{ {
DoSetText(str); DoSetText(str);
@@ -623,6 +649,25 @@ void wxMenuItem::DoSetText( const wxString& str )
#endif #endif
} }
#if wxUSE_ACCEL
wxAcceleratorEntry *wxMenuItem::GetAccel() const
{
if ( !item.GetHotKey() )
{
// nothing
return (wxAcceleratorEntry *)NULL;
}
// as wxGetAccelFromString() looks for TAB, insert a dummy one here
wxString label;
label << wxT('\t') << item.GetHotKey();
return wxGetAccelFromString(label);
}
#endif // wxUSE_ACCEL
void wxMenuItem::Check( bool check ) void wxMenuItem::Check( bool check )
{ {
wxCHECK_RET( m_menuItem, wxT("invalid menu item") ); wxCHECK_RET( m_menuItem, wxT("invalid menu item") );
@@ -658,11 +703,7 @@ wxString wxMenuItem::GetFactoryPath() const
{ {
/* in order to get the pointer to the item we need the item text _without_ underscores */ /* in order to get the pointer to the item we need the item text _without_ underscores */
wxString path( wxT("<main>/") ); wxString path( wxT("<main>/") );
for ( const wxChar *pc = m_text; *pc != wxT('\0'); pc++ ) path += GetLabel();
{
while (*pc == wxT('_')) pc++; /* skip it */
path << *pc;
}
return path; return path;
} }
@@ -673,17 +714,8 @@ wxString wxMenuItem::GetFactoryPath() const
IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler) IMPLEMENT_DYNAMIC_CLASS(wxMenu,wxEvtHandler)
void void wxMenu::Init()
wxMenu::Init( const wxString& title,
long style,
const wxFunction func
)
{ {
m_title = title;
m_items.DeleteContents( TRUE );
m_invokingWindow = (wxWindow *) NULL;
m_style = style;
#if (GTK_MINOR_VERSION > 0) #if (GTK_MINOR_VERSION > 0)
m_accel = gtk_accel_group_new(); m_accel = gtk_accel_group_new();
m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "<main>", m_accel ); m_factory = gtk_item_factory_new( GTK_TYPE_MENU, "<main>", m_accel );
@@ -692,18 +724,6 @@ wxMenu::Init( const wxString& title,
m_menu = gtk_menu_new(); // Do not show! m_menu = gtk_menu_new(); // Do not show!
#endif #endif
m_callback = func;
m_eventHandler = this;
m_clientData = (void*) NULL;
if (m_title.IsNull()) m_title = wxT("");
if (m_title != wxT(""))
{
Append(-2, m_title);
AppendSeparator();
}
m_owner = (GtkWidget*) NULL; m_owner = (GtkWidget*) NULL;
#if (GTK_MINOR_VERSION > 0) #if (GTK_MINOR_VERSION > 0)
@@ -722,40 +742,30 @@ wxMenu::Init( const wxString& title,
//GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" ); //GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/tearoff" );
} }
#endif #endif
// append the title as the very first entry if we have it
if ( !!m_title )
{
Append(-2, m_title);
AppendSeparator();
}
} }
wxMenu::~wxMenu() wxMenu::~wxMenu()
{ {
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
wxMenu *submenu = item->GetSubMenu();
if (submenu)
delete submenu;
node = node->Next();
}
gtk_widget_destroy( m_menu ); gtk_widget_destroy( m_menu );
gtk_object_unref( GTK_OBJECT(m_factory) ); gtk_object_unref( GTK_OBJECT(m_factory) );
// the menu items are deleted by the base class dtor
} }
void wxMenu::SetTitle( const wxString& title ) virtual bool wxMenu::DoAppend(wxMenuItem *mitem)
{ {
// TODO Waiting for something better GtkWidget *menuItem;
m_title = title;
}
const wxString wxMenu::GetTitle() const
{
return m_title;
}
void wxMenu::AppendSeparator()
{
wxMenuItem *mitem = new wxMenuItem(this, wxID_SEPARATOR);
if ( mitem->IsSeparator() )
{
#if (GTK_MINOR_VERSION > 0) #if (GTK_MINOR_VERSION > 0)
GtkItemFactoryEntry entry; GtkItemFactoryEntry entry;
entry.path = "/sep"; entry.path = "/sep";
@@ -767,30 +777,191 @@ void wxMenu::AppendSeparator()
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */ gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
/* this will be wrong for more than one separator. do we care? */ /* this will be wrong for more than one separator. do we care? */
GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, "<main>/sep" ); menuItem = gtk_item_factory_get_widget( m_factory, "<main>/sep" );
#else #else // GTK+ 1.0
GtkWidget *menuItem = gtk_menu_item_new(); menuItem = gtk_menu_item_new();
#endif // GTK 1.2/1.0
}
else if ( mitem->IsSubMenu() )
{
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) 0;
entry.callback_action = 0;
entry.item_type = "<Branch>";
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_item( m_factory, path.mb_str() );
#else // GTK+ 1.0
GtkWidget *menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str());
#endif // GTK 1.2/1.0
gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), subMenu->m_menu );
}
else // a normal item
{
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
entry.callback_action = 0;
if (checkable)
entry.item_type = "<CheckItem>";
else
entry.item_type = "<Item>";
#if wxUSE_ACCEL
// due to an apparent bug in GTK+, we have to use a static buffer here -
// otherwise GTK+ 1.2.2 manages to override the memory we pass to it
// somehow! (VZ)
static char s_accel[32]; // must be big enough for <control><alt><shift>F12
strncpy(s_accel, GetHotKey(*mitem).mb_str(), WXSIZEOF(s_accel));
entry.accelerator = s_accel;
#else // !wxUSE_ACCEL
entry.accelerator = (char*) NULL;
#endif // wxUSE_ACCEL/!wxUSE_ACCEL
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, path.mb_str() );
#else // GTK+ 1.0
GtkWidget *menuItem = checkable ? gtk_check_menu_item_new_with_label( mitem->GetText().mb_str() )
: gtk_menu_item_new_with_label( mitem->GetText().mb_str() );
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer)this );
#endif // GTK+ 1.2/1.0
}
if ( !mitem->IsSeparator() )
{
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer)this );
}
#if GTK_MINOR_VERSION == 0
gtk_menu_append( GTK_MENU(m_menu), menuItem ); gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem ); gtk_widget_show( menuItem );
#endif #endif // GTK+ 1.0
mitem->SetMenuItem(menuItem); mitem->SetMenuItem(menuItem);
m_items.Append( mitem );
return wxMenuBase::DoAppend(mitem);
} }
// VZ: this seems to be GTK+ 1.0 only code, I don't understand why there were
// both specialized versions of Append() and this one before my changes,
// but it seems that the others are better...
#if 0
void wxMenu::Append( wxMenuItem *item )
{
GtkWidget *menuItem = (GtkWidget*) NULL;
if (item->IsSeparator())
menuItem = gtk_menu_item_new();
else if (item->IsSubMenu())
menuItem = gtk_menu_item_new_with_label(item->GetText().mbc_str());
else
menuItem = item->IsCheckable() ? gtk_check_menu_item_new_with_label(item->GetText().mbc_str())
: gtk_menu_item_new_with_label(item->GetText().mbc_str());
if (!item->IsSeparator())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer*)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer*)this );
if (!item->IsSubMenu())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer*)this );
}
}
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
item->SetMenuItem(menuItem);
}
#endif // 0
bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
{
if ( !wxMenuBase::DoInsert(pos, item) )
return FALSE;
wxFAIL_MSG(wxT("not implemented"));
return FALSE;
}
wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
{
if ( !wxMenuBase::DoRemove(item) )
return (wxMenuItem *)NULL;
// TODO: this code doesn't delete the item factory item and this seems
// impossible as of GTK 1.2.6.
gtk_widget_destroy( item->GetMenuItem() );
return item;
}
int wxMenu::FindMenuIdByMenuItem( GtkWidget *menuItem ) const
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetMenuItem() == menuItem)
return item->GetId();
node = node->Next();
}
return wxNOT_FOUND;
}
// ----------------------------------------------------------------------------
// helpers
// ----------------------------------------------------------------------------
#if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL #if (GTK_MINOR_VERSION > 0) && wxUSE_ACCEL
static wxString GetHotKey( const wxMenuItem& item ) static wxString GetHotKey( const wxMenuItem& item )
{ {
wxString hotkey; wxString hotkey;
// as wxGetAccelFromString() looks for TAB, insert a dummy one here wxAcceleratorEntry *accel = item.GetAccel();
wxString label;
label << wxT('\t') << item.GetHotKey();
// but if the hotkey is empty don't do anything
if ( label.length() > 1 )
{
wxAcceleratorEntry *accel = wxGetAccelFromString(label);
if ( accel ) if ( accel )
{ {
int flags = accel->GetFlags(); int flags = accel->GetFlags();
@@ -835,361 +1006,8 @@ static wxString GetHotKey( const wxMenuItem& item )
delete accel; delete accel;
} }
}
return hotkey; return hotkey;
} }
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
void wxMenu::Append( int id, const wxString &item, const wxString &helpStr, bool checkable )
{
wxMenuItem *mitem = new wxMenuItem(this, id, item, helpStr, checkable);
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) gtk_menu_clicked_callback;
entry.callback_action = 0;
if (checkable)
entry.item_type = "<CheckItem>";
else
entry.item_type = "<Item>";
#if wxUSE_ACCEL
// due to an apparent bug in GTK+, we have to use a static buffer here -
// otherwise GTK+ 1.2.2 manages to override the memory we pass to it
// somehow! (VZ)
static char s_accel[32]; // must be big enough for <control><alt><shift>F12
strncpy(s_accel, GetHotKey(*mitem).mb_str(), WXSIZEOF(s_accel));
entry.accelerator = s_accel;
#else
entry.accelerator = (char*) NULL;
#endif
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_widget( m_factory, path.mb_str() );
#else
GtkWidget *menuItem = checkable ? gtk_check_menu_item_new_with_label( mitem->GetText().mb_str() )
: gtk_menu_item_new_with_label( mitem->GetText().mb_str() );
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer)this );
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
#endif
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer)this );
mitem->SetMenuItem(menuItem);
m_items.Append( mitem );
}
void wxMenu::Append( int id, const wxString &item, wxMenu *subMenu, const wxString &helpStr )
{
wxMenuItem *mitem = new wxMenuItem(this, id, item, helpStr, FALSE, subMenu);
#if (GTK_MINOR_VERSION > 0)
/* text has "_" instead of "&" after mitem->SetText() */
wxString text( mitem->GetText() );
/* local buffer in multibyte form */
char buf[200];
strcpy( buf, "/" );
strcat( buf, text.mb_str() );
GtkItemFactoryEntry entry;
entry.path = buf;
entry.callback = (GtkItemFactoryCallback) 0;
entry.callback_action = 0;
entry.item_type = "<Branch>";
gtk_item_factory_create_item( m_factory, &entry, (gpointer) this, 2 ); /* what is 2 ? */
wxString path( mitem->GetFactoryPath() );
GtkWidget *menuItem = gtk_item_factory_get_item( m_factory, path.mb_str() );
#else
GtkWidget *menuItem = gtk_menu_item_new_with_label(mitem->GetText().mbc_str());
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
#endif
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer*)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer*)this );
gtk_menu_item_set_submenu( GTK_MENU_ITEM(menuItem), subMenu->m_menu );
mitem->SetMenuItem(menuItem);
m_items.Append( mitem );
}
void wxMenu::Append( wxMenuItem *item )
{
m_items.Append( item );
GtkWidget *menuItem = (GtkWidget*) NULL;
if (item->IsSeparator())
menuItem = gtk_menu_item_new();
else if (item->IsSubMenu())
menuItem = gtk_menu_item_new_with_label(item->GetText().mbc_str());
else
menuItem = item->IsCheckable() ? gtk_check_menu_item_new_with_label(item->GetText().mbc_str())
: gtk_menu_item_new_with_label(item->GetText().mbc_str());
if (!item->IsSeparator())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "select",
GTK_SIGNAL_FUNC(gtk_menu_hilight_callback),
(gpointer*)this );
gtk_signal_connect( GTK_OBJECT(menuItem), "deselect",
GTK_SIGNAL_FUNC(gtk_menu_nolight_callback),
(gpointer*)this );
if (!item->IsSubMenu())
{
gtk_signal_connect( GTK_OBJECT(menuItem), "activate",
GTK_SIGNAL_FUNC(gtk_menu_clicked_callback),
(gpointer*)this );
}
}
gtk_menu_append( GTK_MENU(m_menu), menuItem );
gtk_widget_show( menuItem );
item->SetMenuItem(menuItem);
}
void wxMenu::Delete( int id )
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetId() == id)
{
/* TODO: this code doesn't delete the item factory item and
this seems impossible as of GTK 1.2.6. */
gtk_widget_destroy( item->GetMenuItem() );
m_items.DeleteNode( node );
return;
}
node = node->Next();
}
}
int wxMenu::FindItem( const wxString itemString ) const
{
wxString s = wxT("");
for ( const wxChar *pc = itemString; *pc != wxT('\0'); pc++ )
{
if (*pc == wxT('&'))
{
pc++; /* skip it */
#if (GTK_MINOR_VERSION > 0)
s << wxT('_');
#endif
}
s << *pc;
}
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetText() == s)
{
return item->GetId();
}
node = node->Next();
}
return wxNOT_FOUND;
}
void wxMenu::Enable( int id, bool enable )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::Enable: no such item") );
item->Enable(enable);
}
bool wxMenu::IsEnabled( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsEnabled: no such item") );
return item->IsEnabled();
}
void wxMenu::Check( int id, bool enable )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::Check: no such item") );
item->Check(enable);
}
bool wxMenu::IsChecked( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, FALSE, wxT("wxMenu::IsChecked: no such item") );
return item->IsChecked();
}
void wxMenu::SetLabel( int id, const wxString &label )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
item->SetText(label);
}
wxString wxMenu::GetLabel( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetLabel: no such item") );
return item->GetText();
}
void wxMenu::SetHelpString( int id, const wxString& helpString )
{
wxMenuItem *item = FindItem(id);
wxCHECK_RET( item, wxT("wxMenu::SetHelpString: no such item") );
item->SetHelp( helpString );
}
wxString wxMenu::GetHelpString( int id ) const
{
wxMenuItem *item = FindItem(id);
wxCHECK_MSG( item, wxT(""), wxT("wxMenu::GetHelpString: no such item") );
return item->GetHelp();
}
int wxMenu::FindMenuIdByMenuItem( GtkWidget *menuItem ) const
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetMenuItem() == menuItem)
return item->GetId();
node = node->Next();
}
return wxNOT_FOUND;
}
wxMenuItem *wxMenu::FindItem(int id) const
{
wxNode *node = m_items.First();
while (node)
{
wxMenuItem *item = (wxMenuItem*)node->Data();
if (item->GetId() == id)
{
return item;
}
node = node->Next();
}
/* Not finding anything here can be correct
* when search the entire menu system for
* an entry -> no error message. */
return (wxMenuItem *) NULL;
}
void wxMenu::SetInvokingWindow( wxWindow *win )
{
m_invokingWindow = win;
}
wxWindow *wxMenu::GetInvokingWindow()
{
return m_invokingWindow;
}
// Update a menu and all submenus recursively. source is the object that has
// the update event handlers defined for it. If NULL, the menu or associated
// window will be used.
void wxMenu::UpdateUI(wxEvtHandler* source)
{
if (!source && GetInvokingWindow())
source = GetInvokingWindow()->GetEventHandler();
if (!source)
source = GetEventHandler();
if (!source)
source = this;
wxNode* node = GetItems().First();
while (node)
{
wxMenuItem* item = (wxMenuItem*) node->Data();
if ( !item->IsSeparator() )
{
wxWindowID id = item->GetId();
wxUpdateUIEvent event(id);
event.SetEventObject( source );
if (source->ProcessEvent(event))
{
if (event.GetSetText())
SetLabel(id, event.GetText());
if (event.GetSetChecked())
Check(id, event.GetChecked());
if (event.GetSetEnabled())
Enable(id, event.GetEnabled());
}
if (item->GetSubMenu())
item->GetSubMenu()->UpdateUI(source);
}
node = node->Next();
}
}

View File

@@ -474,6 +474,8 @@ bool wxDialog::Show(bool show)
if (hWndParent) if (hWndParent)
::BringWindowToTop(hWndParent); ::BringWindowToTop(hWndParent);
} }
if ( m_hWnd )
ShowWindow((HWND) GetHWND(), SW_HIDE); ShowWindow((HWND) GetHWND(), SW_HIDE);
} }
} }

View File

@@ -671,10 +671,9 @@ bool wxFrame::ProcessCommand(int id)
return FALSE; return FALSE;
wxMenuItem *item = bar->FindItemForId(id); wxMenuItem *item = bar->FindItemForId(id);
if ( item && item->IsCheckable() ) if ( item && item->IsCheckable() )
{ {
bar->Check(id, !bar->IsChecked(id)) ; item->Toggle();
} }
wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id); wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id);

View File

@@ -33,6 +33,7 @@
#include "wx/menu.h" #include "wx/menu.h"
#include "wx/utils.h" #include "wx/utils.h"
#include "wx/intl.h" #include "wx/intl.h"
#include "wx/log.h"
#endif #endif
#if wxUSE_OWNER_DRAWN #if wxUSE_OWNER_DRAWN
@@ -40,9 +41,6 @@
#endif #endif
#include "wx/msw/private.h" #include "wx/msw/private.h"
#include "wx/msw/menu.h"
#include "wx/menuitem.h"
#include "wx/log.h"
// other standard headers // other standard headers
#include <string.h> #include <string.h>
@@ -78,33 +76,32 @@ static const int idMenuTitle = -2;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Construct a menu with optional title (then use append) // Construct a menu with optional title (then use append)
void wxMenu::Init(const wxString& title, const wxFunction func ) void wxMenu::Init()
{ {
m_title = title;
m_eventHandler = this;
m_pInvokingWindow = NULL;
m_doBreak = FALSE; m_doBreak = FALSE;
m_noItems = 0;
m_menuBar = NULL;
m_hMenu = (WXHMENU) CreatePopupMenu();
m_savehMenu = 0;
m_topLevelMenu = this;
m_clientData = (void*) NULL;
// create the menu
m_hMenu = (WXHMENU)CreatePopupMenu();
if ( !m_hMenu )
{
wxLogLastError("CreatePopupMenu");
}
// if we have a title, insert it in the beginning of the menu
if ( !!m_title ) if ( !!m_title )
{ {
Append(idMenuTitle, m_title); Append(idMenuTitle, m_title);
AppendSeparator(); AppendSeparator();
} }
Callback(func);
} }
// The wxWindow destructor will take care of deleting the submenus. // The wxWindow destructor will take care of deleting the submenus.
wxMenu::~wxMenu() wxMenu::~wxMenu()
{ {
// free Windows resources // we should free Windows resources only if Windows doesn't do it for us
if ( m_hMenu ) // which happens if we're attached to a menubar or a submenu of another
// menu
if ( !IsAttached() && !GetParent() )
{ {
if ( !::DestroyMenu(GetHmenu()) ) if ( !::DestroyMenu(GetHmenu()) )
{ {
@@ -112,24 +109,6 @@ wxMenu::~wxMenu()
} }
} }
// delete submenus
wxNode *node = m_menuItems.First();
while ( node )
{
wxMenuItem *item = (wxMenuItem *)node->Data();
// Delete child menus.
// Beware: they must not be appended to children list!!!
// (because order of delete is significant)
if ( item->IsSubMenu() )
item->DeleteSubMenu();
wxNode *next = node->Next();
delete item;
delete node;
node = next;
}
#if wxUSE_ACCEL #if wxUSE_ACCEL
// delete accels // delete accels
WX_CLEAR_ARRAY(m_accels); WX_CLEAR_ARRAY(m_accels);
@@ -138,20 +117,64 @@ wxMenu::~wxMenu()
void wxMenu::Break() void wxMenu::Break()
{ {
// this will take effect during the next call to Append()
m_doBreak = TRUE; m_doBreak = TRUE;
} }
// function appends a new item or submenu to the menu
void wxMenu::Append(wxMenuItem *pItem)
{
wxCHECK_RET( pItem != NULL, wxT("can't append NULL item to the menu") );
#if wxUSE_ACCEL #if wxUSE_ACCEL
wxAcceleratorEntry *accel = wxGetAccelFromString(pItem->GetText());
if ( accel ) { int wxMenu::FindAccel(int id) const
m_accels.Add(accel); {
accel->m_command = pItem->GetId(); size_t n, count = m_accels.GetCount();
for ( n = 0; n < count; n++ )
{
if ( m_accels[n]->m_command == id )
return n;
} }
return wxNOT_FOUND;
}
void wxMenu::UpdateAccel(wxMenuItem *item)
{
// find the (new) accel for this item
wxAcceleratorEntry *accel = wxGetAccelFromString(item->GetText());
if ( accel )
accel->m_command = item->GetId();
// find the old one
int n = FindAccel(item->GetId());
if ( n == wxNOT_FOUND )
{
// no old, add new if any
if ( accel )
m_accels.Add(accel);
else
return; // skipping RebuildAccelTable() below
}
else
{
// replace old with new or just remove the old one if no new
delete m_accels[n];
if ( accel )
m_accels[n] = accel;
else
m_accels.Remove(n);
}
if ( IsAttached() )
{
m_menuBar->RebuildAccelTable();
}
}
#endif // wxUSE_ACCEL
// append a new item or submenu to the menu
bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
{
#if wxUSE_ACCEL
UpdateAccel(pItem);
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
UINT flags = 0; UINT flags = 0;
@@ -172,12 +195,11 @@ void wxMenu::Append(wxMenuItem *pItem)
UINT id; UINT id;
wxMenu *submenu = pItem->GetSubMenu(); wxMenu *submenu = pItem->GetSubMenu();
if ( submenu != NULL ) { if ( submenu != NULL ) {
wxASSERT( submenu->GetHMenu() != (WXHMENU) NULL ); wxASSERT_MSG( submenu->GetHMenu(), wxT("invalid submenu") );
submenu->SetParent(this);
id = (UINT)submenu->GetHMenu(); id = (UINT)submenu->GetHMenu();
submenu->m_topLevelMenu = m_topLevelMenu;
submenu->m_savehMenu = (WXHMENU)id;
submenu->m_hMenu = 0;
flags |= MF_POPUP; flags |= MF_POPUP;
} }
@@ -202,12 +224,25 @@ void wxMenu::Append(wxMenuItem *pItem)
pData = (char*)pItem->GetText().c_str(); pData = (char*)pItem->GetText().c_str();
} }
if ( !::AppendMenu(GetHmenu(), flags, id, pData) ) BOOL ok;
if ( pos == (size_t)-1 )
{ {
wxLogLastError("AppendMenu"); ok = ::AppendMenu(GetHmenu(), flags, id, pData);
} }
else else
{ {
ok = ::InsertMenu(GetHmenu(), pos, flags | MF_BYPOSITION, id, pData);
}
if ( !ok )
{
wxLogLastError("Insert or AppendMenu");
return FALSE;
}
else
{
// if we just appended the title, highlight it
#ifdef __WIN32__ #ifdef __WIN32__
if ( (int)id == idMenuTitle ) if ( (int)id == idMenuTitle )
{ {
@@ -224,78 +259,76 @@ void wxMenu::Append(wxMenuItem *pItem)
} }
#endif // __WIN32__ #endif // __WIN32__
m_menuItems.Append(pItem); // if we're already attached to the menubar, we must update it
m_noItems++; if ( IsAttached() )
}
}
void wxMenu::AppendSeparator()
{
Append(new wxMenuItem(this, ID_SEPARATOR));
}
// Pullright item
void wxMenu::Append(int id,
const wxString& label,
wxMenu *SubMenu,
const wxString& helpString)
{
Append(new wxMenuItem(this, id, label, helpString, FALSE, SubMenu));
}
// Ordinary menu item
void wxMenu::Append(int id,
const wxString& label,
const wxString& helpString,
bool checkable)
{
// 'checkable' parameter is useless for Windows.
Append(new wxMenuItem(this, id, label, helpString, checkable));
}
// delete item by id
void wxMenu::Delete(int id)
{
wxMenuItem *item = NULL;
int pos;
wxNode *node;
for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++)
{ {
item = (wxMenuItem *)node->Data(); m_menuBar->Refresh();
if ( item->GetId() == id )
break;
} }
wxCHECK_RET( node, wxT("wxMenu::Delete(): item doesn't exist") ); return TRUE;
HMENU menu = GetHmenu();
wxMenu *pSubMenu = item->GetSubMenu();
if ( pSubMenu != NULL ) {
RemoveMenu(menu, (UINT)pos, MF_BYPOSITION);
pSubMenu->m_hMenu = pSubMenu->m_savehMenu;
pSubMenu->m_savehMenu = 0;
// RemoveChild(item->subMenu);
pSubMenu->m_topLevelMenu = NULL;
// TODO: Why isn't subMenu deleted here???
// Will put this in for now. Assuming this is supposed
// to delete the menu, not just remove it.
item->DeleteSubMenu();
} }
else {
DeleteMenu(menu, (UINT)pos, MF_BYPOSITION);
}
m_menuItems.DeleteNode(node);
delete item;
} }
bool wxMenu::DoAppend(wxMenuItem *item)
{
return wxMenuBase::DoAppend(item) && DoInsertOrAppend(item);
}
bool wxMenu::DoInsert(size_t pos, wxMenuItem *item)
{
return wxMenuBase::DoInsert(pos, item) && DoInsertOrAppend(item, pos);
}
wxMenuItem *wxMenu::DoRemove(wxMenuItem *item)
{
// we need to find the items position in the child list
size_t pos;
wxMenuItemList::Node *node = GetMenuItems().GetFirst();
for ( pos = 0; node; pos++ )
{
if ( node->GetData() == item )
break;
node = node->GetNext();
}
// DoRemove() (unlike Remove) can only be called for existing item!
wxCHECK_MSG( node, NULL, wxT("bug in wxMenu::Remove logic") );
#if wxUSE_ACCEL #if wxUSE_ACCEL
// remove the corresponding accel from the accel table
int n = FindAccel(item->GetId());
if ( n != wxNOT_FOUND )
{
delete m_accels[n];
m_accels.Remove(n);
}
//else: this item doesn't have an accel, nothing to do
#endif // wxUSE_ACCEL
// remove the item from the menu
if ( !::RemoveMenu(GetHmenu(), (UINT)pos, MF_BYPOSITION) )
{
wxLogLastError("RemoveMenu");
}
if ( IsAttached() )
{
// otherwise, the chane won't be visible
m_menuBar->Refresh();
}
// and from internal data structures
return wxMenuBase::DoRemove(item);
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// accelerator helpers // accelerator helpers
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
#if wxUSE_ACCEL
// create the wxAcceleratorEntries for our accels and put them into provided // create the wxAcceleratorEntries for our accels and put them into provided
// array - return the number of accels we have // array - return the number of accels we have
size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
@@ -312,84 +345,7 @@ size_t wxMenu::CopyAccels(wxAcceleratorEntry *accels) const
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// wxMenu functions implemented in wxMenuItem // set wxMenu title
// ---------------------------------------------------------------------------
void wxMenu::Enable(int id, bool Flag)
{
wxMenuItem *item = FindItemForId(id);
wxCHECK_RET( item != NULL, wxT("can't enable non-existing menu item") );
item->Enable(Flag);
}
bool wxMenu::IsEnabled(int id) const
{
wxMenuItem *item = FindItemForId(id);
wxCHECK_MSG( item != NULL, FALSE, wxT("invalid item id") );
return item->IsEnabled();
}
void wxMenu::Check(int id, bool Flag)
{
wxMenuItem *item = FindItemForId(id);
wxCHECK_RET( item != NULL, wxT("can't get status of non-existing menu item") );
item->Check(Flag);
}
bool wxMenu::IsChecked(int id) const
{
wxMenuItem *item = FindItemForId(id);
wxCHECK_MSG( item != NULL, FALSE, wxT("invalid item id") );
return item->IsChecked();
}
void wxMenu::SetLabel(int id, const wxString& label)
{
wxMenuItem *item = FindItemForId(id);
wxCHECK_RET( item, wxT("wxMenu::SetLabel: no such item") );
item->SetText(label);
}
wxString wxMenu::GetLabel(int id) const
{
wxString label;
wxMenuItem *pItem = FindItemForId(id);
if (pItem)
label = pItem->GetText();
else
wxFAIL_MSG(wxT("wxMenu::GetLabel: item doesn't exist"));
return label;
}
void wxMenu::SetHelpString(int itemId, const wxString& helpString)
{
wxMenuItem *item = FindItemForId (itemId);
if (item)
item->SetHelp(helpString);
else
wxFAIL_MSG(wxT("wxMenu::SetHelpString: item doesn't exist"));
}
wxString wxMenu::GetHelpString (int itemId) const
{
wxString help;
wxMenuItem *item = FindItemForId (itemId);
if (item)
help = item->GetHelp();
else
wxFAIL_MSG(wxT("wxMenu::GetHelpString: item doesn't exist"));
return help;
}
// ---------------------------------------------------------------------------
// wxMenu title
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
void wxMenu::SetTitle(const wxString& label) void wxMenu::SetTitle(const wxString& label)
@@ -403,11 +359,11 @@ void wxMenu::SetTitle(const wxString& label)
{ {
if ( !label.IsEmpty() ) if ( !label.IsEmpty() )
{ {
if ( !InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING, if ( !::InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
(unsigned)idMenuTitle, m_title) || (unsigned)idMenuTitle, m_title) ||
!InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) ) !::InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
{ {
wxLogLastError(wxT("InsertMenu")); wxLogLastError("InsertMenu");
} }
} }
} }
@@ -448,12 +404,7 @@ void wxMenu::SetTitle(const wxString& label)
wxLogLastError("SetMenuItemInfo"); wxLogLastError("SetMenuItemInfo");
} }
} }
#endif #endif // Win32
}
const wxString wxMenu::GetTitle() const
{
return m_title;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -481,12 +432,14 @@ bool wxMenu::ProcessCommand(wxCommandEvent & event)
{ {
bool processed = FALSE; bool processed = FALSE;
#if WXWIN_COMPATIBILITY
// Try a callback // Try a callback
if (m_callback) if (m_callback)
{ {
(void)(*(m_callback))(*this, event); (void)(*(m_callback))(*this, event);
processed = TRUE; processed = TRUE;
} }
#endif WXWIN_COMPATIBILITY
// Try the menu's event handler // Try the menu's event handler
if ( !processed && GetEventHandler()) if ( !processed && GetEventHandler())
@@ -503,63 +456,6 @@ bool wxMenu::ProcessCommand(wxCommandEvent & event)
return processed; return processed;
} }
// ---------------------------------------------------------------------------
// Item search
// ---------------------------------------------------------------------------
// Finds the item id matching the given string, -1 if not found.
int wxMenu::FindItem (const wxString& itemString) const
{
wxString itemLabel = wxStripMenuCodes(itemString);
for ( wxNode *node = m_menuItems.First(); node; node = node->Next() )
{
wxMenuItem *item = (wxMenuItem *)node->Data();
if ( item->IsSubMenu() )
{
int ans = item->GetSubMenu()->FindItem(itemString);
if ( ans != wxNOT_FOUND )
return ans;
}
else if ( !item->IsSeparator() )
{
wxString label = wxStripMenuCodes(item->GetText());
if ( itemLabel == label )
return item->GetId();
}
}
return wxNOT_FOUND;
}
wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const
{
if ( itemMenu )
*itemMenu = NULL;
wxMenuItem *item = NULL;
for ( wxNode *node = m_menuItems.First(); node && !item; node = node->Next() )
{
item = (wxMenuItem *)node->Data();
if ( item->GetId() == itemId )
{
if (itemMenu)
*itemMenu = (wxMenu *)this;
}
else if ( item->IsSubMenu() )
{
item = item->GetSubMenu()->FindItemForId(itemId, itemMenu);
}
else
{
// don't exit the loop
item = NULL;
}
}
return item;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// other // other
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -571,8 +467,6 @@ void wxMenu::Attach(wxMenuBar *menubar)
wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") ); wxASSERT_MSG( !m_menuBar, wxT("menu belongs to 2 menubars, expect a crash") );
m_menuBar = menubar; m_menuBar = menubar;
m_savehMenu = m_hMenu;
m_hMenu = 0;
} }
void wxMenu::Detach() void wxMenu::Detach()
@@ -580,8 +474,16 @@ void wxMenu::Detach()
wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") ); wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
m_menuBar = NULL; m_menuBar = NULL;
m_hMenu = m_savehMenu; }
m_savehMenu = 0;
wxWindow *wxMenu::GetWindow() const
{
if ( m_invokingWindow != NULL )
return m_invokingWindow;
else if ( m_menuBar != NULL)
return m_menuBar->GetFrame();
return NULL;
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -674,7 +576,9 @@ WXHMENU wxMenuBar::Create()
void wxMenuBar::EnableTop(size_t pos, bool enable) void wxMenuBar::EnableTop(size_t pos, bool enable)
{ {
int flag = enable ? MF_ENABLED : MF_GRAYED;; wxCHECK_RET( IsAttached(), wxT("doesn't work with unattached menubars") );
int flag = enable ? MF_ENABLED : MF_GRAYED;
EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag); EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | flag);
@@ -683,6 +587,16 @@ void wxMenuBar::EnableTop(size_t pos, bool enable)
void wxMenuBar::SetLabelTop(size_t pos, const wxString& label) void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
{ {
wxCHECK_RET( pos < GetMenuCount(), wxT("invalid menu index") );
m_titles[pos] = label;
if ( !IsAttached() )
{
return;
}
//else: have to modify the existing menu
UINT id; UINT id;
UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION); UINT flagsOld = ::GetMenuState((HMENU)m_hMenu, pos, MF_BYPOSITION);
if ( flagsOld == 0xFFFFFFFF ) if ( flagsOld == 0xFFFFFFFF )
@@ -708,18 +622,16 @@ void wxMenuBar::SetLabelTop(size_t pos, const wxString& label)
{ {
wxLogLastError("ModifyMenu"); wxLogLastError("ModifyMenu");
} }
Refresh();
} }
wxString wxMenuBar::GetLabelTop(size_t pos) const wxString wxMenuBar::GetLabelTop(size_t pos) const
{ {
int len = ::GetMenuString((HMENU)m_hMenu, pos, NULL, 0, MF_BYCOMMAND); wxCHECK_MSG( pos < GetMenuCount(), wxEmptyString,
wxT("invalid menu index in wxMenuBar::GetLabelTop") );
len++; // for the NUL character return m_titles[pos];
wxString label;
::GetMenuString(GetHmenu(), pos, label.GetWriteBuf(len), len, MF_BYCOMMAND);
label.UngetWriteBuf();
return label;
} }
int wxMenuBar::FindMenu(const wxString& title) int wxMenuBar::FindMenu(const wxString& title)
@@ -764,6 +676,14 @@ wxMenu *wxMenuBar::Replace(size_t pos, wxMenu *menu, const wxString& title)
wxLogLastError("InsertMenu"); wxLogLastError("InsertMenu");
} }
#if wxUSE_ACCEL
if ( menuOld->HasAccels() || menu->HasAccels() )
{
// need to rebuild accell table
RebuildAccelTable();
}
#endif // wxUSE_ACCEL
Refresh(); Refresh();
} }
@@ -788,6 +708,14 @@ bool wxMenuBar::Insert(size_t pos, wxMenu *menu, const wxString& title)
wxLogLastError("InsertMenu"); wxLogLastError("InsertMenu");
} }
#if wxUSE_ACCEL
if ( menu->HasAccels() )
{
// need to rebuild accell table
RebuildAccelTable();
}
#endif // wxUSE_ACCEL
Refresh(); Refresh();
} }
@@ -799,8 +727,13 @@ bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
WXHMENU submenu = menu ? menu->GetHMenu() : 0; WXHMENU submenu = menu ? menu->GetHMenu() : 0;
wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") ); wxCHECK_MSG( submenu, FALSE, wxT("can't append invalid menu to menubar") );
if ( !wxMenuBarBase::Append(menu, title) )
return FALSE;
menu->Attach(this); menu->Attach(this);
m_titles.Add(title);
if ( IsAttached() ) if ( IsAttached() )
{ {
if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING, if ( !::AppendMenu(GetHmenu(), MF_POPUP | MF_STRING,
@@ -809,13 +742,17 @@ bool wxMenuBar::Append(wxMenu *menu, const wxString& title)
wxLogLastError(wxT("AppendMenu")); wxLogLastError(wxT("AppendMenu"));
} }
#if wxUSE_ACCEL
if ( menu->HasAccels() )
{
// need to rebuild accell table
RebuildAccelTable();
}
#endif // wxUSE_ACCEL
Refresh(); Refresh();
} }
wxMenuBarBase::Append(menu, title);
m_titles.Add(title);
return TRUE; return TRUE;
} }
@@ -834,6 +771,14 @@ wxMenu *wxMenuBar::Remove(size_t pos)
menu->Detach(); menu->Detach();
#if wxUSE_ACCEL
if ( menu->HasAccels() )
{
// need to rebuild accell table
RebuildAccelTable();
}
#endif // wxUSE_ACCEL
Refresh(); Refresh();
} }
@@ -842,15 +787,11 @@ wxMenu *wxMenuBar::Remove(size_t pos)
return menu; return menu;
} }
void wxMenuBar::Attach(wxFrame *frame)
{
wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
m_menuBarFrame = frame;
#if wxUSE_ACCEL #if wxUSE_ACCEL
// create the accel table - we consider that the menubar construction is
// finished void wxMenuBar::RebuildAccelTable()
{
// merge the accelerators of all menus into one accel table
size_t nAccelCount = 0; size_t nAccelCount = 0;
size_t i, count = GetMenuCount(); size_t i, count = GetMenuCount();
for ( i = 0; i < count; i++ ) for ( i = 0; i < count; i++ )
@@ -872,6 +813,18 @@ void wxMenuBar::Attach(wxFrame *frame)
delete [] accelEntries; delete [] accelEntries;
} }
}
#endif // wxUSE_ACCEL
void wxMenuBar::Attach(wxFrame *frame)
{
wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
m_menuBarFrame = frame;
#if wxUSE_ACCEL
RebuildAccelTable();
#endif // wxUSE_ACCEL #endif // wxUSE_ACCEL
} }
@@ -918,68 +871,3 @@ wxMenuItem *wxMenuBar::FindItem(int id, wxMenu **itemMenu) const
return item; return item;
} }
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
wxWindow *wxMenu::GetWindow() const
{
if ( m_pInvokingWindow != NULL )
return m_pInvokingWindow;
else if ( m_menuBar != NULL)
return m_menuBar->GetFrame();
return NULL;
}
WXHMENU wxMenu::GetHMenu() const
{
if ( m_hMenu != 0 )
return m_hMenu;
else if ( m_savehMenu != 0 )
return m_savehMenu;
wxFAIL_MSG(wxT("wxMenu without HMENU"));
return 0;
}
// Update a menu and all submenus recursively. source is the object that has
// the update event handlers defined for it. If NULL, the menu or associated
// window will be used.
void wxMenu::UpdateUI(wxEvtHandler* source)
{
if (!source && GetInvokingWindow())
source = GetInvokingWindow()->GetEventHandler();
if (!source)
source = GetEventHandler();
if (!source)
source = this;
wxNode* node = GetItems().First();
while (node)
{
wxMenuItem* item = (wxMenuItem*) node->Data();
if ( !item->IsSeparator() )
{
wxWindowID id = item->GetId();
wxUpdateUIEvent event(id);
event.SetEventObject( source );
if (source->ProcessEvent(event))
{
if (event.GetSetText())
SetLabel(id, event.GetText());
if (event.GetSetChecked())
Check(id, event.GetChecked());
if (event.GetSetEnabled())
Enable(id, event.GetEnabled());
}
if (item->GetSubMenu())
item->GetSubMenu()->UpdateUI(source);
}
node = node->Next();
}
}

View File

@@ -42,6 +42,10 @@
#include "wx/menuitem.h" #include "wx/menuitem.h"
#include "wx/log.h" #include "wx/log.h"
#if wxUSE_ACCEL
#include "wx/accel.h"
#endif // wxUSE_ACCEL
#include "wx/msw/private.h" #include "wx/msw/private.h"
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -129,14 +133,6 @@ int wxMenuItem::GetRealId() const
return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId(); return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
} }
// delete the sub menu
// -------------------
void wxMenuItem::DeleteSubMenu()
{
delete m_subMenu;
m_subMenu = NULL;
}
// get item state // get item state
// -------------- // --------------
@@ -148,41 +144,60 @@ bool wxMenuItem::IsChecked() const
return (flag & MF_DISABLED) == 0; return (flag & MF_DISABLED) == 0;
} }
wxString wxMenuItem::GetLabel() const
{
return wxStripMenuCodes(m_text);
}
// accelerators
// ------------
#if wxUSE_ACCEL
wxAcceleratorEntry *wxMenuItem::GetAccel() const
{
return wxGetAccelFromString(GetText());
}
#endif // wxUSE_ACCEL
// change item state // change item state
// ----------------- // -----------------
void wxMenuItem::Enable(bool bDoEnable) void wxMenuItem::Enable(bool enable)
{ {
if ( m_isEnabled != bDoEnable ) { if ( m_isEnabled == enable )
return;
long rc = EnableMenuItem(GetHMenuOf(m_parentMenu), long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
GetRealId(), GetRealId(),
MF_BYCOMMAND | MF_BYCOMMAND |
(bDoEnable ? MF_ENABLED : MF_GRAYED)); (enable ? MF_ENABLED : MF_GRAYED));
if ( rc == -1 ) { if ( rc == -1 ) {
wxLogLastError("EnableMenuItem"); wxLogLastError("EnableMenuItem");
} }
wxMenuItemBase::Enable(m_isEnabled); wxMenuItemBase::Enable(enable);
}
} }
void wxMenuItem::Check(bool bDoCheck) void wxMenuItem::Check(bool check)
{ {
wxCHECK_RET( m_isCheckable, wxT("only checkable items may be checked") ); wxCHECK_RET( m_isCheckable, wxT("only checkable items may be checked") );
if ( m_isChecked != bDoCheck ) { if ( m_isChecked == check )
return;
long rc = CheckMenuItem(GetHMenuOf(m_parentMenu), long rc = CheckMenuItem(GetHMenuOf(m_parentMenu),
GetId(), GetRealId(),
MF_BYCOMMAND | MF_BYCOMMAND |
(bDoCheck ? MF_CHECKED : MF_UNCHECKED)); (check ? MF_CHECKED : MF_UNCHECKED));
if ( rc == -1 ) { if ( rc == -1 ) {
wxLogLastError("CheckMenuItem"); wxLogLastError("CheckMenuItem");
} }
wxMenuItemBase::Check(m_isChecked); wxMenuItemBase::Check(check);
}
} }
void wxMenuItem::SetText(const wxString& text) void wxMenuItem::SetText(const wxString& text)
@@ -195,6 +210,11 @@ void wxMenuItem::SetText(const wxString& text)
OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) ); OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
HMENU hMenu = GetHMenuOf(m_parentMenu); HMENU hMenu = GetHMenuOf(m_parentMenu);
wxCHECK_RET( hMenu, wxT("menuitem without menu") );
#if wxUSE_ACCEL
m_parentMenu->UpdateAccel(this);
#endif // wxUSE_ACCEL
UINT id = GetRealId(); UINT id = GetRealId();
UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND); UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);