Removed wxImageList overview, and other @ref fixes.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52273 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Bryan Petty
2008-03-03 03:05:58 +00:00
parent 95d3881fed
commit 032e27aad0
6 changed files with 479 additions and 498 deletions

View File

@@ -97,7 +97,6 @@ The following is a basic categorization of them:
@li @subpage overview_treectrl @li @subpage overview_treectrl
@li @subpage overview_listctrl @li @subpage overview_listctrl
@li @subpage overview_splitterwindow @li @subpage overview_splitterwindow
@li @subpage overview_imagelist
@li @subpage overview_bookctrl @li @subpage overview_bookctrl
@li @subpage overview_tips @li @subpage overview_tips
@li @subpage overview_docview @li @subpage overview_docview

View File

@@ -8,131 +8,131 @@
/*! /*!
@page overview_app wxApp overview @page overview_app wxApp Overview
Classes: wxApp Classes: wxApp
@li @ref overview_app_intro @li @ref overview_app_intro
@li @ref overview_app_shutdown @li @ref overview_app_shutdown
<hr> <hr>
@section overview_app_intro Introduction @section overview_app_intro Introduction
A wxWidgets application does not have a @e main procedure; the equivalent is the A wxWidgets application does not have a @e main procedure; the equivalent is
wxApp::OnInit member defined for a class derived from wxApp. the wxApp::OnInit member defined for a class derived from wxApp.
@e OnInit will usually create a top window as a bare minimum. @e OnInit will usually create a top window as a bare minimum. Unlike in earlier
Unlike in earlier versions of wxWidgets, OnInit does not return a frame. Instead it versions of wxWidgets, OnInit does not return a frame. Instead it returns a
returns a boolean value which indicates whether processing should continue (@true) boolean value which indicates whether processing should continue (@true) or not
or not (@false). You call wxApp::SetTopWindow to let wxWidgets know about the top window. (@false). You call wxApp::SetTopWindow to let wxWidgets know about the top
window.
Note that the program's command line arguments, represented by @e argc Note that the program's command line arguments, represented by @e argc and
and @e argv, are available from within wxApp member functions. @e argv, are available from within wxApp member functions.
An application closes by destroying all windows. Because all frames must An application closes by destroying all windows. Because all frames must be
be destroyed for the application to exit, it is advisable to use parent destroyed for the application to exit, it is advisable to use parent frames
frames wherever possible when creating new frames, so that deleting the wherever possible when creating new frames, so that deleting the top level
top level frame will automatically delete child frames. The alternative frame will automatically delete child frames. The alternative is to explicitly
is to explicitly delete child frames in the top-level frame's wxCloseEvent delete child frames in the top-level frame's wxCloseEvent handler.
handler.
In emergencies the wxExit function can be called to kill the In emergencies the wxExit function can be called to kill the application
application however normally the application shuts down automatically, however normally the application shuts down automatically, see
see @ref overview_app_shutdown. @ref overview_app_shutdown.
An example of defining an application follows: An example of defining an application follows:
@code @code
class DerivedApp : public wxApp class DerivedApp : public wxApp
{ {
public: public:
virtual bool OnInit(); virtual bool OnInit();
}; };
IMPLEMENT_APP(DerivedApp) IMPLEMENT_APP(DerivedApp)
bool DerivedApp::OnInit() bool DerivedApp::OnInit()
{ {
wxFrame *the_frame = new wxFrame(NULL, ID_MYFRAME, argv[0]); wxFrame *the_frame = new wxFrame(NULL, ID_MYFRAME, argv[0]);
... ...
the_frame->Show(true); the_frame->Show(true);
SetTopWindow(the_frame); SetTopWindow(the_frame);
return true; return true;
} }
@endcode @endcode
Note the use of IMPLEMENT_APP(appClass), which allows wxWidgets to dynamically create Note the use of IMPLEMENT_APP(appClass), which allows wxWidgets to dynamically
an instance of the application object at the appropriate point in wxWidgets initialization. create an instance of the application object at the appropriate point in
Previous versions of wxWidgets used to rely on the creation of a global application object, wxWidgets initialization. Previous versions of wxWidgets used to rely on the
but this is no longer recommended, because required global initialization may not have creation of a global application object, but this is no longer recommended,
been performed at application object construction time. because required global initialization may not have been performed at
application object construction time.
You can also use DECLARE_APP(appClass) in a header file to declare the wxGetApp function You can also use DECLARE_APP(appClass) in a header file to declare the wxGetApp
which returns a reference to the application object. Otherwise you can only use the global function which returns a reference to the application object. Otherwise you can
@c wxTheApp pointer which is of type @c wxApp *. only use the global @c wxTheApp pointer which is of type @c wxApp*.
@section overview_app_shutdown Application Shutdown
@section overview_app_shutdown Application shutdown The application normally shuts down when the last of its top level windows is
closed. This is normally the expected behaviour and means that it is enough to
call wxWindow::Close() in response to the "Exit" menu command if your program
has a single top level window. If this behaviour is not desirable
wxApp::SetExitOnFrameDelete can be called to change it.
The application normally shuts down when the last of its top level windows is Note that such logic doesn't apply for the windows shown before the program
closed. This is normally the expected behaviour and means that it is enough to enters the main loop: in other words, you can safely show a dialog from
call wxWindow::Close() in response to the @c "Exit" menu command if your program has a wxApp::OnInit and not be afraid that your application terminates when this
single top level window. If this behaviour is not desirable wxApp::SetExitOnFrameDelete dialog -- which is the last top level window for the moment -- is closed.
can be called to change it.
Note that such logic doesn't apply for the windows shown before the program enters the Another aspect of the application shutdown is wxApp::OnExit which is called
main loop: in other words, you can safely show a dialog from wxApp::OnInit and not be when the application exits but @e before wxWidgets cleans up its internal
afraid that your application terminates when this dialog -- which is the last top level structures. You should delete all wxWidgets object that you created by the time
window for the moment -- is closed. OnExit finishes.
Another aspect of the application shutdown is wxApp::OnExit In particular, do @b not destroy them from application class' destructor! For
which is called when the application exits but @e before wxWidgets cleans up example, this code may crash:
its internal structures. You should delete all wxWidgets object that you
created by the time OnExit finishes.
In particular, do @b not destroy them from application class' destructor! @code
For example, this code may crash: class MyApp : public wxApp
{
public:
wxCHMHelpController m_helpCtrl;
...
};
@endcode
@code The reason for that is that @c m_helpCtrl is a member object and is thus
class MyApp : public wxApp destroyed from MyApp destructor. But MyApp object is deleted after wxWidgets
{ structures that wxCHMHelpController depends on were uninitialized! The solution
public: is to destroy HelpCtrl in @e OnExit:
wxCHMHelpController m_helpCtrl;
...
};
@endcode
The reason for that is that @c m_helpCtrl is a member object and is @code
thus destroyed from MyApp destructor. But MyApp object is deleted after class MyApp : public wxApp
wxWidgets structures that wxCHMHelpController depends on were {
uninitialized! The solution is to destroy HelpCtrl in @e OnExit: public:
wxCHMHelpController *m_helpCtrl;
...
};
@code bool MyApp::OnInit()
class MyApp : public wxApp {
{ ...
public: m_helpCtrl = new wxCHMHelpController;
wxCHMHelpController *m_helpCtrl; ...
... }
};
bool MyApp::OnInit() int MyApp::OnExit()
{ {
... delete m_helpCtrl;
m_helpCtrl = new wxCHMHelpController; return 0;
... }
} @endcode
int MyApp::OnExit()
{
delete m_helpCtrl;
return 0;
}
@endcode
*/ */

View File

@@ -8,435 +8,441 @@
/*! /*!
@page overview_arc Archive formats such as zip @page overview_arc Archive Formats
The archive classes handle archive formats such as zip, tar, rar and cab. The archive classes handle archive formats such as zip, tar, rar and cab.
Currently wxZip and wxTar classes are included. Currently wxZip and wxTar classes are included.
For each archive type, there are the following classes (using zip here For each archive type, there are the following classes (using zip here as an
as an example): example):
@li wxZipInputStream: input stream @li wxZipInputStream: Input stream
@li wxZipOutputStream: output stream @li wxZipOutputStream: Output stream
@li wxZipEntry: holds the meta-data for an entry (e.g. filename, timestamp, etc.) @li wxZipEntry: Holds meta-data for an entry (e.g. filename, timestamp, etc.)
There are also abstract wxArchive classes that can be used to write code There are also abstract wxArchive classes that can be used to write code that
that can handle any of the archive types, see @ref overview_arc_generic. can handle any of the archive types, see @ref overview_arc_generic.
Also see wxFileSystem for a higher level interface that Also see wxFileSystem for a higher level interface that can handle archive
can handle archive files in a generic way. files in a generic way.
The classes are designed to handle archives on both seekable streams such The classes are designed to handle archives on both seekable streams such as
as disk files, or non-seekable streams such as pipes and sockets disk files, or non-seekable streams such as pipes and sockets (see
(see @ref overview_arc_noseek). @ref overview_arc_noseek).
See also wxFileSystem. See also wxFileSystem.
@li @ref overview_arc_create @li @ref overview_arc_create
@li @ref overview_arc_extract @li @ref overview_arc_extract
@li @ref overview_arc_modify @li @ref overview_arc_modify
@li @ref overview_arc_byname @li @ref overview_arc_byname
@li @ref overview_arc_generic @li @ref overview_arc_generic
@li @ref overview_arc_noseek @li @ref overview_arc_noseek
<hr> <hr>
@section overview_arc_create Creating an archive @section overview_arc_create Creating an Archive
Call wxArchiveOutputStream::PutNextEntry() to create each new entry in the archive, Call wxArchiveOutputStream::PutNextEntry() to create each new entry in the
then write the entry's data. archive, then write the entry's data. Another call to PutNextEntry() closes the
Another call to PutNextEntry() closes the current entry and begins the next. current entry and begins the next. For example:
For example:
@code @code
wxFFileOutputStream out(_T("test.zip")); wxFFileOutputStream out(_T("test.zip"));
wxZipOutputStream zip(out); wxZipOutputStream zip(out);
wxTextOutputStream txt(zip); wxTextOutputStream txt(zip);
wxString sep(wxFileName::GetPathSeparator()); wxString sep(wxFileName::GetPathSeparator());
zip.PutNextEntry(_T("entry1.txt")); zip.PutNextEntry(_T("entry1.txt"));
txt << _T("Some text for entry1.txt\n"); txt << _T("Some text for entry1.txt\n");
zip.PutNextEntry(_T("subdir") + sep + _T("entry2.txt")); zip.PutNextEntry(_T("subdir") + sep + _T("entry2.txt"));
txt << _T("Some text for subdir/entry2.txt\n"); txt << _T("Some text for subdir/entry2.txt\n");
@endcode @endcode
The name of each entry can be a full path, which makes it possible to The name of each entry can be a full path, which makes it possible to store
store entries in subdirectories. entries in subdirectories.
@section overview_arc_extract Extracting an archive @section overview_arc_extract Extracting an Archive
wxArchiveInputStream::GetNextEntry() returns a pointer to entry object containing the wxArchiveInputStream::GetNextEntry() returns a pointer to entry object
meta-data for the next entry in the archive (and gives away ownership). containing the meta-data for the next entry in the archive (and gives away
ownership).
Reading from the input stream then returns the entry's data. Reading from the input stream then returns the entry's data. Eof() becomes
Eof() becomes @true after an attempt has been made to read past the end of the entry's data. @true after an attempt has been made to read past the end of the entry's data.
When there are no more entries, GetNextEntry() returns @NULL and sets Eof(). When there are no more entries, GetNextEntry() returns @NULL and sets Eof().
@code @code
auto_ptr<wxZipEntry> entry; auto_ptr<wxZipEntry> entry;
wxFFileInputStream in(_T("test.zip")); wxFFileInputStream in(_T("test.zip"));
wxZipInputStream zip(in); wxZipInputStream zip(in);
while (entry.reset(zip.GetNextEntry()), entry.get() != NULL) while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
{ {
// access meta-data // access meta-data
wxString name = entry->GetName(); wxString name = entry->GetName();
// read 'zip' to access the entry's data // read 'zip' to access the entry's data
} }
@endcode @endcode
@section overview_arc_modify Modifying an archive @section overview_arc_modify Modifying an Archive
To modify an existing archive, write a new copy of the archive to a new file, To modify an existing archive, write a new copy of the archive to a new file,
making any necessary changes along the way and transferring any unchanged making any necessary changes along the way and transferring any unchanged
entries using wxArchiveOutputStream::CopyEntry(). entries using wxArchiveOutputStream::CopyEntry().
For archive types which compress entry data, CopyEntry() is likely to be For archive types which compress entry data, CopyEntry() is likely to be much
much more efficient than transferring the data using Read() and Write() more efficient than transferring the data using Read() and Write() since it
since it will copy them without decompressing and recompressing them. will copy them without decompressing and recompressing them.
In general modifications are not possible without rewriting the archive, In general modifications are not possible without rewriting the archive, though
though it may be possible in some limited cases. Even then, rewriting the it may be possible in some limited cases. Even then, rewriting the archive is
archive is usually a better choice since a failure can be handled without usually a better choice since a failure can be handled without losing the whole
losing the whole archive. wxTempFileOutputStream can be helpful to do this. archive. wxTempFileOutputStream can be helpful to do this.
For example to delete all entries matching the pattern "*.txt": For example to delete all entries matching the pattern "*.txt":
@code @code
auto_ptr<wxFFileInputStream> in(new wxFFileInputStream(_T("test.zip"))); auto_ptr<wxFFileInputStream> in(new wxFFileInputStream(_T("test.zip")));
wxTempFileOutputStream out(_T("test.zip")); wxTempFileOutputStream out(_T("test.zip"));
wxZipInputStream inzip(*in); wxZipInputStream inzip(*in);
wxZipOutputStream outzip(out); wxZipOutputStream outzip(out);
auto_ptr<wxZipEntry> entry; auto_ptr<wxZipEntry> entry;
// transfer any meta-data for the archive as a whole (the zip comment // transfer any meta-data for the archive as a whole (the zip comment
// in the case of zip) // in the case of zip)
outzip.CopyArchiveMetaData(inzip); outzip.CopyArchiveMetaData(inzip);
// call CopyEntry for each entry except those matching the pattern // call CopyEntry for each entry except those matching the pattern
while (entry.reset(inzip.GetNextEntry()), entry.get() != NULL) while (entry.reset(inzip.GetNextEntry()), entry.get() != NULL)
if (!entry->GetName().Matches(_T("*.txt"))) if (!entry->GetName().Matches(_T("*.txt")))
if (!outzip.CopyEntry(entry.release(), inzip)) if (!outzip.CopyEntry(entry.release(), inzip))
break; break;
// close the input stream by releasing the pointer to it, do this // close the input stream by releasing the pointer to it, do this
// before closing the output stream so that the file can be replaced // before closing the output stream so that the file can be replaced
in.reset(); in.reset();
// you can check for success as follows // you can check for success as follows
bool success = inzip.Eof() && outzip.Close() && out.Commit(); bool success = inzip.Eof() && outzip.Close() && out.Commit();
@endcode @endcode
@section overview_arc_byname Looking up an archive entry by name @section overview_arc_byname Looking Up an Archive Entry by Name
Also see wxFileSystem for a higher level interface that is Also see wxFileSystem for a higher level interface that is more convenient for
more convenient for accessing archive entries by name. accessing archive entries by name.
To open just one entry in an archive, the most efficient way is To open just one entry in an archive, the most efficient way is to simply
to simply search for it linearly by calling wxArchiveInputStream::GetNextEntry() search for it linearly by calling wxArchiveInputStream::GetNextEntry() until
until the required entry is found. This works both for archives on seekable and the required entry is found. This works both for archives on seekable and
non-seekable streams. non-seekable streams.
The format of filenames in the archive is likely to be different The format of filenames in the archive is likely to be different from the local
from the local filename format. For example zips and tars use filename format. For example zips and tars use unix style names, with forward
unix style names, with forward slashes as the path separator, slashes as the path separator, and absolute paths are not allowed. So if on
and absolute paths are not allowed. So if on Windows the file Windows the file "C:\MYDIR\MYFILE.TXT" is stored, then when reading the entry
"C:\MYDIR\MYFILE.TXT" is stored, then when reading the entry back back wxArchiveEntry::GetName() will return "MYDIR\MYFILE.TXT". The conversion
wxArchiveEntry::GetName() will return "MYDIR\MYFILE.TXT". into the internal format and back has lost some information.
The conversion into the internal format and back has lost some information.
So to avoid ambiguity when searching for an entry matching a local name, So to avoid ambiguity when searching for an entry matching a local name, it is
it is better to convert the local name to the archive's internal format better to convert the local name to the archive's internal format and search
and search for that: for that:
@code @code
auto_ptr<wxZipEntry> entry; auto_ptr<wxZipEntry> entry;
// convert the local name we are looking for into the internal format // convert the local name we are looking for into the internal format
wxString name = wxZipEntry::GetInternalName(localname); wxString name = wxZipEntry::GetInternalName(localname);
// open the zip // open the zip
wxFFileInputStream in(_T("test.zip")); wxFFileInputStream in(_T("test.zip"));
wxZipInputStream zip(in); wxZipInputStream zip(in);
// call GetNextEntry() until the required internal name is found // call GetNextEntry() until the required internal name is found
do { do
entry.reset(zip.GetNextEntry()); {
} entry.reset(zip.GetNextEntry());
while (entry.get() != NULL && entry->GetInternalName() != name); }
while (entry.get() != NULL && entry->GetInternalName() != name);
if (entry.get() != NULL) { if (entry.get() != NULL)
// read the entry's data... {
} // read the entry's data...
@endcode }
@endcode
To access several entries randomly, it is most efficient to transfer the To access several entries randomly, it is most efficient to transfer the entire
entire catalogue of entries to a container such as a std::map or a catalogue of entries to a container such as a std::map or a wxHashMap then
wxHashMap then entries looked up by name can be opened using the entries looked up by name can be opened using the
wxArchiveInputStream::OpenEntry() method. wxArchiveInputStream::OpenEntry() method.
@code
WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
ZipCatalog::iterator it;
wxZipEntry *entry;
ZipCatalog cat;
// open the zip
wxFFileInputStream in(_T("test.zip"));
wxZipInputStream zip(in);
// load the zip catalog
while ((entry = zip.GetNextEntry()) != NULL) {
wxZipEntry*& current = cat[entry->GetInternalName()];
// some archive formats can have multiple entries with the same name
// (e.g. tar) though it is an error in the case of zip
delete current;
current = entry;
}
// open an entry by name
if ((it = cat.find(wxZipEntry::GetInternalName(localname))) != cat.end()) {
zip.OpenEntry(*it->second);
// ... now read entry's data
}
@endcode
To open more than one entry simultaneously you need more than one
underlying stream on the same archive:
@code
// opening another entry without closing the first requires another
// input stream for the same file
wxFFileInputStream in2(_T("test.zip"));
wxZipInputStream zip2(in2);
if ((it = cat.find(wxZipEntry::GetInternalName(local2))) != cat.end())
zip2.OpenEntry(*it->second);
@endcode
@code
WX_DECLARE_STRING_HASH_MAP(wxZipEntry*, ZipCatalog);
ZipCatalog::iterator it;
wxZipEntry *entry;
ZipCatalog cat;
// open the zip
wxFFileInputStream in(_T("test.zip"));
wxZipInputStream zip(in);
// load the zip catalog
while ((entry = zip.GetNextEntry()) != NULL)
{
wxZipEntry*& current = cat[entry->GetInternalName()];
// some archive formats can have multiple entries with the same name
// (e.g. tar) though it is an error in the case of zip
delete current;
current = entry;
}
// open an entry by name
if ((it = cat.find(wxZipEntry::GetInternalName(localname))) != cat.end())
{
zip.OpenEntry(*it->second);
// ... now read entry's data
}
@endcode
To open more than one entry simultaneously you need more than one underlying
stream on the same archive:
@code
// opening another entry without closing the first requires another
// input stream for the same file
wxFFileInputStream in2(_T("test.zip"));
wxZipInputStream zip2(in2);
if ((it = cat.find(wxZipEntry::GetInternalName(local2))) != cat.end())
zip2.OpenEntry(*it->second);
@endcode
@section overview_arc_generic Generic Archive Programming
Also see wxFileSystem for a higher level interface that can handle archive
files in a generic way.
The specific archive classes, such as the wxZip classes, inherit from the
following abstract classes which can be used to write code that can handle any
of the archive types:
@li wxArchiveInputStream: Input stream
@li wxArchiveOutputStream: Output stream
@li wxArchiveEntry: Holds the meta-data for an entry (e.g. filename)
In order to able to write generic code it's necessary to be able to create
instances of the classes without knowing which archive type is being used.
To allow this there is a class factory for each archive type, derived from
wxArchiveClassFactory, that can create the other classes.
For example, given wxArchiveClassFactory* factory, streams and entries can be
created like this:
@code
// create streams without knowing their type
auto_ptr<wxArchiveInputStream> inarc(factory->NewStream(in));
auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
// create an empty entry object
auto_ptr<wxArchiveEntry> entry(factory->NewEntry());
@endcode
For the factory itself, the static member wxArchiveClassFactory::Find() can be
used to find a class factory that can handle a given file extension or mime
type. For example, given @e filename:
@code
const wxArchiveClassFactory *factory;
factory = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
if (factory)
stream = factory->NewStream(new wxFFileInputStream(filename));
@endcode
@e Find() does not give away ownership of the returned pointer, so it does not
need to be deleted.
There are similar class factories for the filter streams that handle the
compression and decompression of a single stream, such as wxGzipInputStream.
These can be found using wxFilterClassFactory::Find().
For example, to list the contents of archive @e filename:
@code
auto_ptr<wxInputStream> in(new wxFFileInputStream(filename));
if (in->IsOk())
{
// look for a filter handler, e.g. for '.gz'
const wxFilterClassFactory *fcf;
fcf = wxFilterClassFactory::Find(filename, wxSTREAM_FILEEXT);
if (fcf)
{
in.reset(fcf->NewStream(in.release()));
// pop the extension, so if it was '.tar.gz' it is now just '.tar'
filename = fcf->PopExtension(filename);
}
// look for a archive handler, e.g. for '.zip' or '.tar'
const wxArchiveClassFactory *acf;
acf = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT);
if (acf)
{
auto_ptr<wxArchiveInputStream> arc(acf->NewStream(in.release()));
auto_ptr<wxArchiveEntry> entry;
// list the contents of the archive
while ((entry.reset(arc->GetNextEntry())), entry.get() != NULL)
std::wcout << entry->GetName().c_str() << "\n";
}
else
{
wxLogError(_T("can't handle '%s'"), filename.c_str());
}
}
@endcode
@section overview_arc_generic Generic archive programming
Also see wxFileSystem for a higher level interface that @section overview_arc_noseek Archives on Non-Seekable Streams
can handle archive files in a generic way.
In general, handling archives on non-seekable streams is done in the same way
The specific archive classes, such as the wxZip classes, inherit from as for seekable streams, with a few caveats.
the following abstract classes which can be used to write code that can
handle any of the archive types: The main limitation is that accessing entries randomly using
wxArchiveInputStream::OpenEntry() is not possible, the entries can only be
@li wxArchiveInputStream: input stream accessed sequentially in the order they are stored within the archive.
@li wxArchiveOutputStream: output stream
@li wxArchiveEntry: holds the meta-data for an entry (e.g. filename) For each archive type, there will also be other limitations which will depend
on the order the entries' meta-data is stored within the archive. These are not
In order to able to write generic code it's necessary to be able to create too difficult to deal with, and are outlined below.
instances of the classes without knowing which archive type is being used.
@subsection overview_arc_noseek_entrysize PutNextEntry and the Entry Size
To allow this there is a class factory for each archive type, derived from
wxArchiveClassFactory, that can create the other classes. When writing archives, some archive formats store the entry size before the
entry's data (tar has this limitation, zip doesn't). In this case the entry's
For example, given @e wxArchiveClassFactory* factory, streams and size must be passed to wxArchiveOutputStream::PutNextEntry() or an error
entries can be created like this: occurs.
@code This is only an issue on non-seekable streams, since otherwise the archive
// create streams without knowing their type output stream can seek back and fix up the header once the size of the entry is
auto_ptr<wxArchiveInputStream> inarc(factory->NewStream(in)); known.
auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
For generic programming, one way to handle this is to supply the size whenever
// create an empty entry object it is known, and rely on the error message from the output stream when the
auto_ptr<wxArchiveEntry> entry(factory->NewEntry()); operation is not supported.
@endcode
@subsection overview_arc_noseek_weak GetNextEntry and the Weak Reference Mechanism
For the factory itself, the static member wxArchiveClassFactory::Find().
can be used to find a class factory that can handle a given file Some archive formats do not store all an entry's meta-data before the entry's
extension or mime type. For example, given @e filename: data (zip is an example). In this case, when reading from a non-seekable
stream, wxArchiveInputStream::GetNextEntry() can only return a partially
@code populated wxArchiveEntry object - not all the fields are set.
const wxArchiveClassFactory *factory;
factory = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT); The input stream then keeps a weak reference to the entry object and updates it
when more meta-data becomes available. A weak reference being one that does not
if (factory) prevent you from deleting the wxArchiveEntry object - the input stream only
stream = factory->NewStream(new wxFFileInputStream(filename)); attempts to update it if it is still around.
@endcode
The documentation for each archive entry type gives the details of what
@e Find does not give away ownership of the returned pointer, so it meta-data becomes available and when. For generic programming, when the worst
does not need to be deleted. case must be assumed, you can rely on all the fields of wxArchiveEntry being
fully populated when GetNextEntry() returns, with the the following exceptions:
There are similar class factories for the filter streams that handle the
compression and decompression of a single stream, such as wxGzipInputStream. @li wxArchiveEntry::GetSize(): Guaranteed to be available after the entry has
These can be found using wxFilterClassFactory::Find(). been read to wxInputStream::Eof(), or wxArchiveInputStream::CloseEntry()
has been called.
For example, to list the contents of archive @e filename: @li wxArchiveEntry::IsReadOnly(): Guaranteed to be available after the end of
the archive has been reached, i.e. after GetNextEntry() returns @NULL and
@code Eof() is @true.
auto_ptr<wxInputStream> in(new wxFFileInputStream(filename));
This mechanism allows wxArchiveOutputStream::CopyEntry() to always fully
if (in->IsOk()) preserve entries' meta-data. No matter what order order the meta-data occurs
{ within the archive, the input stream will always have read it before the output
// look for a filter handler, e.g. for '.gz' stream must write it.
const wxFilterClassFactory *fcf;
fcf = wxFilterClassFactory::Find(filename, wxSTREAM_FILEEXT); @subsection overview_arc_noseek_notifier wxArchiveNotifier
if (fcf) {
in.reset(fcf->NewStream(in.release())); Notifier objects can be used to get a notification whenever an input stream
// pop the extension, so if it was '.tar.gz' it is now just '.tar' updates a wxArchiveEntry object's data via the weak reference mechanism.
filename = fcf->PopExtension(filename);
} Consider the following code which renames an entry in an archive. This is the
usual way to modify an entry's meta-data, simply set the required field before
// look for a archive handler, e.g. for '.zip' or '.tar' writing it with wxArchiveOutputStream::CopyEntry():
const wxArchiveClassFactory *acf;
acf = wxArchiveClassFactory::Find(filename, wxSTREAM_FILEEXT); @code
if (acf) { auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
auto_ptr<wxArchiveInputStream> arc(acf->NewStream(in.release())); auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
auto_ptr<wxArchiveEntry> entry; auto_ptr<wxArchiveEntry> entry;
// list the contents of the archive outarc->CopyArchiveMetaData(*arc);
while ((entry.reset(arc->GetNextEntry())), entry.get() != NULL)
std::wcout << entry->GetName().c_str() << "\n"; while (entry.reset(arc->GetNextEntry()), entry.get() != NULL)
} {
else { if (entry->GetName() == from)
wxLogError(_T("can't handle '%s'"), filename.c_str()); entry->SetName(to);
} if (!outarc->CopyEntry(entry.release(), *arc))
} break;
@endcode }
bool success = arc->Eof() && outarc->Close();
@endcode
@section overview_arc_noseek Archives on non-seekable streams
However, for non-seekable streams, this technique cannot be used for fields
In general, handling archives on non-seekable streams is done in the same such as wxArchiveEntry::IsReadOnly(), which are not necessarily set when
way as for seekable streams, with a few caveats. wxArchiveInputStream::GetNextEntry() returns.
The main limitation is that accessing entries randomly using In this case a wxArchiveNotifier can be used:
wxArchiveInputStream::OpenEntry() is not possible, the entries can only be
accessed sequentially in the order they are stored within the archive. @code
class MyNotifier : public wxArchiveNotifier
For each archive type, there will also be other limitations which will {
depend on the order the entries' meta-data is stored within the archive. public:
These are not too difficult to deal with, and are outlined below. void OnEntryUpdated(wxArchiveEntry& entry) { entry.SetIsReadOnly(false); }
};
@subsection overview_arc_noseek_entrysize PutNextEntry and the entry size @endcode
When writing archives, some archive formats store the entry size before The meta-data changes are done in your notifier's
the entry's data (tar has this limitation, zip doesn't). In this case wxArchiveNotifier::OnEntryUpdated() method, then wxArchiveEntry::SetNotifier()
the entry's size must be passed to wxArchiveOutputStream::PutNextEntry() is called before CopyEntry():
or an error occurs.
@code
This is only an issue on non-seekable streams, since otherwise the archive auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
output stream can seek back and fix up the header once the size of the auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
entry is known. auto_ptr<wxArchiveEntry> entry;
MyNotifier notifier;
For generic programming, one way to handle this is to supply the size
whenever it is known, and rely on the error message from the output outarc->CopyArchiveMetaData(*arc);
stream when the operation is not supported.
while (entry.reset(arc->GetNextEntry()), entry.get() != NULL)
@subsection overview_arc_noseek_weak GetNextEntry and the weak reference mechanism {
entry->SetNotifier(notifier);
Some archive formats do not store all an entry's meta-data before the if (!outarc->CopyEntry(entry.release(), *arc))
entry's data (zip is an example). In this case, when reading from a break;
non-seekable stream, wxArchiveInputStream::GetNextEntry() can only return }
a partially populated wxArchiveEntry object - not all the fields are set.
bool success = arc->Eof() && outarc->Close();
The input stream then keeps a weak reference to the entry object and @endcode
updates it when more meta-data becomes available. A weak reference being
one that does not prevent you from deleting the wxArchiveEntry object - the SetNotifier() calls OnEntryUpdated() immediately, then the input stream calls
input stream only attempts to update it if it is still around. it again whenever it sets more fields in the entry. Since OnEntryUpdated() will
be called at least once, this technique always works even when it is not
The documentation for each archive entry type gives the details strictly necessary to use it. For example, changing the entry name can be done
of what meta-data becomes available and when. For generic programming, this way too and it works on seekable streams as well as non-seekable.
when the worst case must be assumed, you can rely on all the fields
of wxArchiveEntry being fully populated when GetNextEntry() returns,
with the the following exceptions:
@li wxArchiveEntry::GetSize(): guaranteed to be available after the
entry has been read to wxInputStream::Eof(), or wxArchiveInputStream::CloseEntry()
has been called
@li wxArchiveEntry::IsReadOnly(): guaranteed to be available after the end of
the archive has been reached, i.e. after GetNextEntry() returns @NULL and
Eof() is @true
This mechanism allows wxArchiveOutputStream::CopyEntry() to always fully
preserve entries' meta-data. No matter what order order the meta-data occurs
within the archive, the input stream will always have read it before the output
stream must write it.
@subsection overview_arc_noseek_notifier wxArchiveNotifier
Notifier objects can be used to get a notification whenever an input
stream updates a wxArchiveEntry object's data via the weak reference mechanism.
Consider the following code which renames an entry in an archive.
This is the usual way to modify an entry's meta-data, simply set the
required field before writing it with wxArchiveOutputStream::CopyEntry():
@code
auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
auto_ptr<wxArchiveEntry> entry;
outarc->CopyArchiveMetaData(*arc);
while (entry.reset(arc->GetNextEntry()), entry.get() != NULL) {
if (entry->GetName() == from)
entry->SetName(to);
if (!outarc->CopyEntry(entry.release(), *arc))
break;
}
bool success = arc->Eof() && outarc->Close();
@endcode
However, for non-seekable streams, this technique cannot be used for
fields such as wxArchiveEntry::IsReadOnly(), which are not necessarily set when
wxArchiveInputStream::GetNextEntry() returns.
In this case a wxArchiveNotifier can be used:
@code
class MyNotifier : public wxArchiveNotifier
{
public:
void OnEntryUpdated(wxArchiveEntry& entry) { entry.SetIsReadOnly(false); }
};
@endcode
The meta-data changes are done in your notifier's wxArchiveNotifier::OnEntryUpdated()
method, then wxArchiveEntry::SetNotifier() is called before CopyEntry():
@code
auto_ptr<wxArchiveInputStream> arc(factory->NewStream(in));
auto_ptr<wxArchiveOutputStream> outarc(factory->NewStream(out));
auto_ptr<wxArchiveEntry> entry;
MyNotifier notifier;
outarc->CopyArchiveMetaData(*arc);
while (entry.reset(arc->GetNextEntry()), entry.get() != NULL) {
entry->SetNotifier(notifier);
if (!outarc->CopyEntry(entry.release(), *arc))
break;
}
bool success = arc->Eof() && outarc->Close();
@endcode
SetNotifier() calls OnEntryUpdated() immediately, then the input
stream calls it again whenever it sets more fields in the entry. Since
OnEntryUpdated() will be called at least once, this technique always
works even when it is not strictly necessary to use it. For example,
changing the entry name can be done this way too and it works on seekable
streams as well as non-seekable.
*/ */

View File

@@ -1,24 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
// Name: imagelist.h
// Purpose: topic overview
// Author: wxWidgets team
// RCS-ID: $Id$
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
/*!
@page overview_imagelist wxImageList overview
Classes: wxImageList
An image list is a list of images that may have transparent areas.
The class helps an application organise a collection of images
so that they can be referenced by integer index instead of by
pointer.
Image lists are used in wxNotebook, wxListCtrl, wxTreeCtrl and
some other control classes.
*/

View File

@@ -50,13 +50,13 @@ you need wxHelp and the wxHelpController class to control wxHelp.
GUI applications aren't all graphical wizardry. List and hash table needs are GUI applications aren't all graphical wizardry. List and hash table needs are
catered for by wxList and wxHashMap. You will undoubtedly need some catered for by wxList and wxHashMap. You will undoubtedly need some
platform-independent @ref functions_file, and you may find it handy to platform-independent @ref page_func_cat_file, and you may find it handy to
maintain and search a list of paths using wxPathList. There's many maintain and search a list of paths using wxPathList. There's many
@ref functions_miscellany of operating system methods and other functions. @ref page_func_cat_misc of operating system methods and other functions.
@seealso @seealso
@li @ref page_categories @li @ref page_class_cat
*/ */

View File

@@ -8,7 +8,7 @@
/*! /*!
@page overview_xrc XML Based Resource System @page overview_xrc XML Based Resource System (XRC)
Classes: wxXmlResource, wxXmlResourceHandler Classes: wxXmlResource, wxXmlResourceHandler