a couple more overview updates, tweak the logo image

This commit is contained in:
Robin Dunn
2016-05-26 23:14:58 -07:00
parent eeec9c5a41
commit 85197c91b1
3 changed files with 294 additions and 156 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -8,30 +8,47 @@
==============================================
Like with all the other GUI frameworks, the control of flow in wxPython applications is event-based: the program
normally performs most of its actions in response to the events generated by the user. These events can be
triggered by using the input devices (such as keyboard, mouse, joystick) directly or, more commonly, by a standard
control which synthesizes such input events into higher level events: for example, a :ref:`Button` can generate
a click event when the user presses the left mouse button on it and then releases it without pressing ``Esc`` in
the meanwhile. There are also events which don't directly correspond to the user actions, such as :ref:`TimerEvent`.
Like with all the other GUI frameworks, the control of flow in
wxPython applications is event-based: the program normally performs
most of its actions in response to the events generated by the
user. These events can be triggered by using the input devices (such
as keyboard, mouse, joystick) directly or, more commonly, by a
standard control which synthesizes such input events into higher level
events: for example, a :ref:`wx.Button` can generate a click event when
the user presses the left mouse button on it and then releases it
without pressing ``Esc`` in the meanwhile. There are also events which
don't directly correspond to the user actions, such as
:ref:`wx.TimerEvent`.
But in all cases wxPython represents these events in a uniform way and allows you to handle them in the same way
wherever they originate from. And while the events are normally generated by wxPython itself, you can also do this,
which is especially useful when using custom events (see :ref:`Custom Event Summary <custom event summary>`).
But in all cases wxPython represents these events in a uniform way and
allows you to handle them in the same way wherever they originate
from. And while the events are normally generated by wxPython itself,
you can also do this, which is especially useful when using custom
events (see :ref:`Custom Event Summary <custom event summary>`).
To be more precise, each event is described by:
- `Event type`: this is simply a value of type `EventType` which uniquely identifies the type of the event.
For example, clicking on a button, selecting an item from a list box and pressing a key on the keyboard all
generate events with different event types.
- `Event class` carried by the event: each event has some information associated with it and this data is represented
by an object of a class derived from :ref:`Event`. Events of different types can use the same event class, for
example both button click and listbox selection events use :ref:`CommandEvent` class (as do all the other simple
control events), but the key press event uses :ref:`KeyEvent` as the information associated with it is different.
- `Event source`: :ref:`Event` stores the object which generated the event and, for windows, its identifier (see
:ref:`Window Identifiers <window identifiers>`). As it is common to have more than one object generating events of
the same type (e.g. a typical window contains several buttons, all generating the same button click event), checking
the event source object or its id allows to distinguish between them.
- **Event type**: this is simply a value of type `EventType` which
uniquely identifies the type of the event. For example, clicking on
a button, selecting an item from a list box and pressing a key on
the keyboard all generate events with different event types.
- **Event class**: carried by the event: each event has some information
associated with it and this data is represented by an object of a
class derived from :ref:`wx.Event`. Events of different types can
use the same event class, for example both button click and listbox
selection events use :ref:`wx.CommandEvent` class (as do all the
other simple control events), but the key press event uses
:ref:`wx.KeyEvent` as the information associated with it is
different.
- **Event source**: :ref:`wx.Event` stores the object which generated the
event and, for windows, its identifier (see :ref:`Window Identifiers
<window identifiers>`). As it is common to have more than one object
generating events of the same type (e.g. a typical window contains
several buttons, all generating the same button click event),
checking the event source object or its id allows to distinguish
between them.
@@ -40,13 +57,14 @@ To be more precise, each event is described by:
Event Handling
--------------
There is one principal way to handle events in wxPython, which uses :meth:`EvtHandler.Bind` () call and can be used
to bind and unbind the handlers dynamically, i.e. during run-time depending on some conditions. It also allows the direct
binding of events to:
There is one principal way to handle events in wxPython, which uses
the :meth:`wx.EvtHandler.Bind` call and can be used to bind and unbind
the handlers dynamically, i.e. during run-time depending on some
conditions. It also allows the direct binding of events to:
- A handler method in another object.
- A handler method in the same or another object.
- An ordinary function like a static method or a global function.
- An arbitrary function.
- An arbitrary callable object.
@@ -55,50 +73,53 @@ binding of events to:
Dynamic Event Handling
----------------------
Let us start by looking at the syntax: in any place in your code, but usually in the code of the class defining the handler
itself, call its `Bind()` method like this::
Let us start by looking at the syntax: in any place in your code, but
usually in the code of the class defining the handler itself, call its
``Bind()`` method like this::
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
# Other initialization code...
self.Bind(wx.EVT_MENU, self.OnExit, id=wx.ID_EXIT)
Event handlers can be bound at any moment. For example, it's possible to do some initialization first and only bind the
handlers if and when it succeeds. This can avoid the need to test that the object was properly initialized in the event
handlers themselves. With `Bind()` they simply won't be called if it wasn't correctly initialized.
Event handlers can be bound at any moment. For example, it's possible
to do some initialization first and only bind the handlers if and when
it succeeds. This can avoid the need to test that the object was
properly initialized in the event handlers themselves. With ``Bind()``
they simply won't be called if it wasn't correctly initialized.
As a slight extension of the above, the handlers can also be unbound at any time with :meth:`EvtHandler.Unbind` () (and maybe rebound later).
As a slight extension of the above, the handlers can also be unbound
at any time with :meth:`wx.EvtHandler.Unbind` (and maybe rebound
later).
Almost last but very, very far from least is the flexibility which allows to bind an event to:
Almost last but very, very far from least is the flexibility which
allows to bind an event to:
- A method in another object.
- An ordinary function like a static method or a global function.
- An arbitrary function.
Let us now look at more examples of how to use different event handlers using the two overloads of `Bind()` function:
first one for the object methods and the other one for arbitrary functors (callable objects, including simple functions).
Let us now look at more examples of how to use different event
handlers using the two overloads of ``Bind()`` function: first one for
the object methods and the other one for arbitrary functors (callable
objects, including simple functions).
In addition to using a method of the object generating the event itself, you can use a method from a completely different
object as an event handler::
In addition to using a method of the object generating the event
itself, you can use a method from a completely different object as an
event handler::
def OnFrameExit(event):
# Do something useful.
pass
pass
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
# Other initialization code...
@@ -107,7 +128,8 @@ object as an event handler::
Note that `MyFrameHandler` doesn't need to derive from :ref:`EvtHandler`.
Note that `MyFrameHandler` doesn't need to derive from
:ref:`wx.EvtHandler`.
@@ -116,36 +138,63 @@ Note that `MyFrameHandler` doesn't need to derive from :ref:`EvtHandler`.
How Events are Processed
------------------------
The previous sections explain how to define event handlers but don't address the question of how exactly
wxPython finds the handler to call for the given event. This section describes the algorithm used in detail.
The previous sections explain how to define event handlers but don't
address the question of how exactly wxPython finds the handler to call
for the given event. This section describes the algorithm used in
detail.
When an event is received from the windowing system, wxPython calls :meth:`EvtHandler.ProcessEvent` () on
the first event handler object belonging to the window generating the event. The normal order of event table
searching by `ProcessEvent()` is as follows, with the event processing stopping as soon as a handler is found
(unless the handler calls :meth:`Event.Skip` () in which case it doesn't count as having handled the event
and the search continues):
When an event is received from the windowing system, wxPython calls
:meth:`wx.EvtHandler.ProcessEvent` on the first event handler object
belonging to the window generating the event. The normal order of
event table searching by ``ProcessEvent`` is as follows, with the
event processing stopping as soon as a handler is found (unless the
handler calls :meth:`wx.Event.Skip` in which case it doesn't count as
having handled the event and the search continues):
1. Before anything else happens, :meth:`AppConsole.FilterEvent` () is called. If it returns anything but -1 (default),
the event handling stops immediately.
2. If this event handler is disabled via a call to :meth:`EvtHandler.SetEvtHandlerEnabled` () the next three
steps are skipped and the event handler resumes at step (5).
3. If the object is a :ref:`Window` and has an associated validator, :ref:`Validator` gets a chance to process the event.
4. The list of dynamically bound event handlers, i.e., those for which `Bind()` was called, is consulted.
5. The event table containing all the handlers defined using the event table macros in this class and its base classes
is examined. Notice that this means that any event handler defined in a base class will be executed at this step.
6. The event is passed to the next event handler, if any, in the event handler chain, i.e., the steps (1) to (4) are done
for it. Usually there is no next event handler so the control passes to the next step but see :ref:`Event Handlers Chain <event handlers chain>`
for how the next handler may be defined.
7. If the object is a :ref:`Window` and the event is set to propagate (by default only :ref:`CommandEvent` -derived events are set to propagate),
then the processing restarts from the step (1) (and excluding the step (7)) for the parent window. If this object is not a window
but the next handler exists, the event is passed to its parent if it is a window. This ensures that in a common case of
(possibly several) non-window event handlers pushed on top of a window, the event eventually reaches the window parent.
8. Finally, i.e., if the event is still not processed, the :ref:`App` object itself (which derives from :ref:`EvtHandler`)
gets a last chance to process it.
1. Before anything else happens, :meth:`wx.AppConsole.FilterEvent` is
called. If it returns anything but -1 (default), the event handling
stops immediately.
2. If this event handler is disabled via a call to
:meth:`wx.EvtHandler.SetEvtHandlerEnabled` the next three steps are
skipped and the event handler resumes at step (5).
3. If the object is a :ref:`wx.Window` and has an associated validator,
:ref:`wx.Validator` gets a chance to process the event.
4. The list of dynamically bound event handlers, i.e., those for which
``Bind()`` was called, is consulted.
5. The event table containing all the handlers defined using the event
table macros in this class and its base classes is examined. Notice
that this means that any event handler defined in a base class will
be executed at this step.
6. The event is passed to the next event handler, if any, in the event
handler chain, i.e., the steps (1) to (4) are done for it. Usually
there is no next event handler so the control passes to the next
step but see :ref:`Event Handlers Chain <event handlers chain>` for
how the next handler may be defined.
7. If the object is a :ref:`wx.Window` and the event is set to
propagate (by default only event types derived from
:ref:`wx.CommandEvent` are set to propagate), then the processing
restarts from the step (1) (and excluding the step (7)) for the
parent window. If this object is not a window but the next handler
exists, the event is passed to its parent if it is a window. This
ensures that in a common case of (possibly several) non-window
event handlers pushed on top of a window, the event eventually
reaches the window parent.
8. Finally, i.e., if the event is still not processed, the
:ref:`wx.App` object itself (which derives from
:ref:`wx.EvtHandler`) gets a last chance to process it.
**Please pay close attention to step 6!** People often overlook or get confused by this powerful feature of the wxPython
event processing system. The details of event propagation up the window hierarchy are described in the next section.
**Please pay close attention to step 6!** People often overlook or get
confused by this powerful feature of the wxPython event processing
system. The details of event propagation up the window hierarchy are
described in the next section.
@@ -154,32 +203,49 @@ event processing system. The details of event propagation up the window hierarch
How Events Propagate Upwards
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As mentioned above, the events of the classes deriving from :ref:`CommandEvent` are propagated by default to the parent
window if they are not processed in this window itself. But although by default only the command events are propagated
like this, other events can be propagated as well because the event handling code uses :meth:`Event.ShouldPropagate` ()
to check whether an event should be propagated. It is also possible to propagate the event only a limited number of times
and not until it is processed (or a top level parent window is reached).
As mentioned above, the events of the classes deriving from
:ref:`wx.CommandEvent` are propagated by default to the parent window if
they are not processed in this window itself. But although by default
only the command events are propagated like this, other events can be
propagated as well because the event handling code uses
:meth:`wx.Event.ShouldPropagate` to check whether an event should be
propagated. It is also possible to propagate the event only a limited
number of times and not until it is processed (or a top level parent
window is reached).
Finally, there is another additional complication (which, in fact, simplifies life of wxPython programmers significantly):
when propagating the command events up to the parent window, the event propagation stops when it reaches the parent dialog,
if any. This means that you don't risk getting unexpected events from the dialog controls (which might be left unprocessed
by the dialog itself because it doesn't care about them) when a modal dialog is popped up. The events do propagate beyond
the frames, however. The rationale for this choice is that there are only a few frames in a typical application and their
parent-child relation are well understood by the programmer while it may be difficult, if not impossible, to track down all
the dialogs that may be popped up in a complex program (remember that some are created automatically by wxPython).
If you need to specify a different behaviour for some reason, you can use :meth:`Window.SetExtraStyle` (``WS_EX_BLOCK_EVENTS``)
explicitly to prevent the events from being propagated beyond the given window or unset this flag for the dialogs that
have it on by default.
Finally, there is another additional complication (which, in fact,
simplifies life of wxPython programmers significantly): when
propagating the command events up to the parent window, the event
propagation stops when it reaches the parent dialog, if any. This
means that you don't risk getting unexpected events from the dialog
controls (which might be left unprocessed by the dialog itself because
it doesn't care about them) when a modal dialog is popped up. The
events do propagate beyond the frames, however. The rationale for this
choice is that there are only a few frames in a typical application
and their parent-child relation are well understood by the programmer
while it may be difficult, if not impossible, to track down all the
dialogs that may be popped up in a complex program (remember that some
are created automatically by wxPython). If you need to specify a
different behaviour for some reason, you can use
:meth:`wx.Window.SetExtraStyle` (``wx.WS_EX_BLOCK_EVENTS``) explicitly
to prevent the events from being propagated beyond the given window or
unset this flag for the dialogs that have it on by default.
Typically events that deal with a window as a window (size, motion, paint, mouse, keyboard, etc.) are sent only to the window.
Events that have a higher level of meaning or are generated by the window itself (button click, menu select, tree expand, etc.)
are command events and are sent up to the parent to see if it is interested in the event. More precisely, as said above, all
event classes not deriving from :ref:`CommandEvent` (see the :ref:`Event` inheritance diagram) do not propagate upward.
Typically events that deal with a window as a window (size, motion,
paint, mouse, keyboard, etc.) are sent only to the window. Events
that have a higher level of meaning or are generated by the window
itself (button click, menu select, tree expand, etc.) are command
events and are sent up to the parent to see if it is interested in the
event. More precisely, as said above, all event classes not deriving
from :ref:`wx.CommandEvent` (see the :ref:`wx.Event` inheritance
diagram) do not propagate upward.
In some cases, it might be desired by the programmer to get a certain number of system events in a parent window, for
example all key events sent to, but not used by, the native controls in a dialog. In this case, a special event handler
will have to be written that will override `ProcessEvent()` in order to pass all events (or any selection of them) to the
parent window.
In some cases, it might be desired by the programmer to get a certain
number of system events in a parent window, for example all key events
sent to, but not used by, the native controls in a dialog. In this
case, a special event handler will have to be written that will
override ``ProcessEvent()`` in order to pass all events (or any
selection of them) to the parent window.
.. _event handlers chain:
@@ -187,18 +253,21 @@ parent window.
Event Handlers Chain
^^^^^^^^^^^^^^^^^^^^
The step 4 of the event propagation algorithm checks for the next handler in the event handler chain. This chain can be formed
using :meth:`EvtHandler.SetNextHandler` ():
Step 4 of the event propagation algorithm checks for the next
handler in the event handler chain. This chain can be formed using
:meth:`wx.EvtHandler.SetNextHandler`:
.. figure:: _static/images/overviews/overview_events_chain.png
:align: center
|
(referring to the image, if `A.ProcessEvent` is called and it doesn't handle the event, `B.ProcessEvent` will be called and so on...).
(Referring to the image, if ``A.ProcessEvent`` is called and it doesn't
handle the event, ``B.ProcessEvent`` will be called and so on...).
Additionally, in the case of :ref:`Window` you can build a stack (implemented using :ref:`EvtHandler` double-linked list) using
:meth:`Window.PushEventHandler` ():
Additionally, in the case of :ref:`wx.Window` you can build a stack
(implemented using :ref:`wx.EvtHandler` double-linked list) using
:meth:`wx.Window.PushEventHandler`:
.. figure:: _static/images/overviews/overview_events_winstack.png
:align: center
@@ -207,9 +276,12 @@ Additionally, in the case of :ref:`Window` you can build a stack (implemented us
(referring to the image, if `W.ProcessEvent` is called, it immediately calls `A.ProcessEvent`; if nor A nor B handle the event,
then the :ref:`Window` itself is used -- i.e. the dynamically bind event handlers and static event table entries of :ref:`Window`
are looked as the last possibility, after all pushed event handlers were tested).
(Referring to the image, if ``W.ProcessEvent`` is called, it
immediately calls ``A.ProcessEvent``; if nor A nor B handle the event,
then the :ref:`wx.Window` itself is used -- i.e. the dynamically bind
event handlers and static event table entries of :ref:`wx.Window` are
looked as the last possibility, after all pushed event handlers were
tested).
By default the chain is empty, i.e. there is no next handler.
@@ -222,10 +294,13 @@ Custom Event Summary
General approach
^^^^^^^^^^^^^^^^
Custom event classes allow you to create more polished-seeming controls by allowing the control's user to process updates
without needing to sub-class the control. However, to effectively use events, you normally need to create custom event classes.
Custom event classes allow you to create more polished-seeming
controls by allowing the control's user to process updates without
needing to sub-class the control. However, to effectively use events,
you normally need to create custom event classes.
This recipe gives you some boilerplate code for creating your own custom event classes::
This recipe gives you some boilerplate code for creating your own
custom event classes::
import wx
import wx.lib.newevent
@@ -240,7 +315,8 @@ You can bind the events normally via either binding syntax::
EVT_SOME_NEW_EVENT(self, self.handler)
You can also attach arbitrary data to the event during its creation, then post it to whatever window you choose::
You can also attach arbitrary data to the event during its creation,
then post it to whatever window you choose::
# Create the event
evt = SomeNewEvent(attr1="hello", attr2=654)
@@ -248,8 +324,10 @@ You can also attach arbitrary data to the event during its creation, then post i
wx.PostEvent(target, evt)
When handling events with such arbitrary data, you can fetch the data via attributes, named the same as the names
passed in during the event instance creation. That is, given the two keyword arguments passed to SomeNewEvent above::
When handling events with such arbitrary data, you can fetch the data
via attributes, named the same as the names passed in during the event
instance creation. That is, given the two keyword arguments passed to
``SomeNewEvent`` above::
def handler(self, evt):
@@ -269,22 +347,34 @@ Miscellaneous Notes
User Generated Events vs Programmatically Generated Events
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
While generically a :ref:`Event` can be generated both by user actions (e.g., resize of a :ref:`Window`) and by calls to functions
(e.g., :meth:`Window.SetSize`), wxPython controls normally send :ref:`CommandEvent` -derived events only for the user-generated
While generically a :ref:`wx.Event` can be generated both by user actions
(e.g., resize of a :ref:`wx.Window`) and by calls to functions (e.g.,
:meth:`wx.Window.SetSize`), wxPython controls normally send
:ref:`wx.CommandEvent` -derived events only for the user-generated
events. The only exceptions to this rule are:
- :meth:`BookCtrlBase.AddPage` No event-free alternatives
- :meth:`BookCtrlBase.AdvanceSelection` No event-free alternatives
- :meth:`BookCtrlBase.DeletePage` No event-free alternatives
- :meth:`Notebook.SetSelection`: Use :meth:`Notebook.ChangeSelection` instead, as :meth:`Notebook.SetSelection` is deprecated
- :meth:`TreeCtrl.Delete`: No event-free alternatives
- :meth:`TreeCtrl.DeleteAllItems`: No event-free alternatives
- :meth:`TreeCtrl.EditLabel`: No event-free alternatives
- All :ref:`TextCtrl` methods
- :meth:`wx.BookCtrlBase.AddPage` No event-free alternatives
- :meth:`wx.BookCtrlBase.AdvanceSelection` No event-free alternatives
- :meth:`wx.BookCtrlBase.DeletePage` No event-free alternatives
- :meth:`wx.Notebook.SetSelection`: Use :meth:`wx.Notebook.ChangeSelection`
instead, as :meth:`wx.Notebook.SetSelection` is deprecated
- :meth:`wx.TreeCtrl.Delete`: No event-free alternatives
- :meth:`wx.TreeCtrl.DeleteAllItems`: No event-free alternatives
- :meth:`wx.TreeCtrl.EditLabel`: No event-free alternatives
- All :ref:`wx.TextCtrl` methods
:meth:`TextEntry.ChangeValue` can be used instead of :meth:`TextEntry.SetValue` but the other functions, such as :meth:`TextEntry.Replace`
or :meth:`TextCtrl.WriteText` don't have event-free equivalents.
:meth:`wx.TextEntry.ChangeValue` can be used instead of
:meth:`wx.TextEntry.SetValue` but the other functions, such as
:meth:`wx.TextEntry.Replace` or :meth:`wx.TextCtrl.WriteText` don't
have event-free equivalents.
@@ -293,20 +383,31 @@ or :meth:`TextCtrl.WriteText` don't have event-free equivalents.
Window Identifiers
^^^^^^^^^^^^^^^^^^
Window identifiers are integers, and are used to uniquely determine window identity in the event system (though you can use it
for other purposes). In fact, identifiers do not need to be unique across your entire application as long they are unique within
the particular context you're interested in, such as a frame and its children. You may use the ``ID_OK`` identifier, for example,
on any number of dialogs as long as you don't have several within the same dialog.
Window identifiers are integers, and are used to uniquely determine
window identity in the event system (though you can use it for other
purposes). In fact, identifiers do not need to be unique across your
entire application as long they are unique within the particular
context you're interested in, such as a frame and its children. You
may use the ``wx.ID_OK`` identifier, for example, on any number of
dialogs as long as you don't have several within the same dialog.
If you pass ``ID_ANY`` or -1 to a window constructor, an identifier will be generated for you automatically by wxPython. This is useful
when you don't care about the exact identifier either because you're not going to process the events from the control being created
or because you process the events from all controls in one place (in which case you should specify ``ID_ANY`` in the :meth:`EvtHandler.Bind`
call as well). The automatically generated identifiers are always negative and so will never conflict with the user-specified
identifiers which must be always positive.
If you pass ``wx.ID_ANY`` or -1 to a window constructor, an identifier
will be generated for you automatically by wxPython. This is useful
when you don't care about the exact identifier either because you're
not going to process the events from the control being created or
because you process the events from all controls in one place (in
which case you should specify ``wx.ID_ANY`` in the
:meth:`wx.EvtHandler.Bind` call as well). The automatically generated
identifiers are always negative and so will never conflict with the
user-specified identifiers which must be always positive.
.. seealso:: See :ref:`Standard event identifiers <standard event identifiers>` for the list of standard identifiers available.
.. seealso:: See :ref:`Standard event identifiers <standard event identifiers>`
for the list of standard identifiers available.
You can use ``ID_HIGHEST`` to determine the number above which it is safe to define your own identifiers. Or, you can use identifiers below ``ID_LOWEST``.
Finally, you can allocate identifiers dynamically using :func:`NewId` () function too. If you use :func:`NewId` () consistently in your
application, you can be sure that your identifiers don't conflict accidentally.
You can use ``wx.ID_HIGHEST`` to determine the number above which it is
safe to define your own identifiers. Or, you can use identifiers below
``wx.ID_LOWEST``. Finally, you can allocate identifiers dynamically
using :func:`wx.NewId` function too. If you use :func:`wx.NewId`
consistently in your application, you can be sure that your
identifiers don't conflict accidentally.

View File

@@ -7,34 +7,59 @@
|phoenix_title| **FileSystem Overview**
========================================
The wxHTML library uses a **virtual** file systems mechanism similar to the one used in Midnight Commander, Dos Navigator, FAR or almost any modern file manager.
The wxHTML library uses a **virtual** file systems mechanism similar
to the one used in Midnight Commander, Dos Navigator, FAR or almost
any modern file manager.
It allows the user to access data stored in archives as if they were ordinary files. On-the-fly generated files that exist only in memory are also supported.
It allows the user to access data stored in archives as if they were
ordinary files. On-the-fly generated files that exist only in memory
are also supported.
Classes
-------
Three classes are used in order to provide virtual file systems mechanism:
Three classes are used in order to provide virtual file systems
mechanism:
* The :ref:`FSFile` class provides information about opened file (name, input stream, mime type and anchor).
* The :ref:`FileSystem` class is the interface. Its main methods are :meth:`FileSystem.ChangePathTo` and :meth:`FileSystem.OpenFile`. This class is most often used by the end user.
* The :ref:`FileSystemHandler` is the core of virtual file systems mechanism. You can derive your own handler and pass it to the VFS mechanism. You can derive your
own handler and pass it to the :meth:`FileSystem.AddHandler` method. In the new handler you only need to override the :meth:`FileSystemHandler.OpenFile` and
:meth:`FileSystemHandler.CanOpen` methods.
* The :ref:`wx.FSFile` class provides information about opened file
(name, input stream, mime type and anchor).
* The :ref:`wx.FileSystem` class is the interface. Its main methods are
:meth:`wx.FileSystem.ChangePathTo` and
:meth:`wx.FileSystem.OpenFile`. This class is most often used by the
end user.
* The :ref:`wx.FileSystemHandler` is the core of virtual file systems
mechanism. You can derive your own handler and pass it to the VFS
mechanism. You can derive your own handler and pass it to the
:meth:`wx.FileSystem.AddHandler` method. In the new handler you only
need to override the :meth:`wx.FileSystemHandler.OpenFile` and
:meth:`wx.FileSystemHandler.CanOpen` methods.
Locations
---------
Locations (aka filenames aka addresses) are constructed from four parts:
Locations (aka filenames aka addresses) are constructed from four
parts:
* **protocol** - handler can recognize if it is able to open a file by checking its protocol. Examples are ``"http"``, ``"file"`` or ``"ftp"``.
* **right location** - is the name of file within the protocol. In ``"http://www.wxwidgets.org/index.html"`` the right location is ``"//www.wxwidgets.org/index.html"``.
* **anchor** - an anchor is optional and is usually not present. In ``"index.htm#chapter2"`` the anchor is ``"chapter2"``.
* **left location** - this is usually an empty string. It is used by 'local' protocols such as ZIP. See the :ref:`Combined Protocols <combined protocols>` paragraph for details.
* **protocol** - handler can recognize if it is able to open a file by
checking its protocol. Examples are ``"http"``, ``"file"`` or
``"ftp"``.
* **right location** - is the name of file within the protocol. In
``"http://www.wxwidgets.org/index.html"`` the right location is
``"//www.wxwidgets.org/index.html"``.
* **anchor** - an anchor is optional and is usually not present. In
``"index.htm#chapter2"`` the anchor is ``"chapter2"``.
* **left location** - this is usually an empty string. It is used by
'local' protocols such as ZIP. See the :ref:`Combined Protocols
<combined protocols>` paragraph for details.
.. _combined protocols:
@@ -44,11 +69,15 @@ Combined Protocols
The left location precedes the protocol in the URL string.
It is not used by global protocols like HTTP but it becomes handy when nesting protocols - for example you may want to access files in a ZIP archive:
It is not used by global protocols like HTTP but it becomes handy when
nesting protocols - for example you may want to access files in a ZIP
archive:
``file:archives/cpp_doc.zip#zip:reference/fopen.htm#syntax``
In this example, the protocol is ``"zip"``, right location is ``"reference/fopen.htm"``, anchor is ``"syntax"`` and left location is ``file:archives/cpp_doc.zip``.
In this example, the protocol is ``"zip"``, right location is
``"reference/fopen.htm"``, anchor is ``"syntax"`` and left location is
``file:archives/cpp_doc.zip``.
There are two protocols used in this example: "zip" and "file".
@@ -60,11 +89,20 @@ File Systems Included in wxHTML
The following virtual file system handlers are part of wxPython so far:
* :ref:`ArchiveFSHandler`: A handler for archives such as zip and tar. URLs examples: ``"archive.zip#zip:filename"``, ``"archive.tar.gz#gzip:#tar:filename"``.
* :ref:`FilterFSHandler`: A handler for compression schemes such as gzip. URLs are in the form, e.g.: ``"document.ps.gz#gzip:"``.
* :ref:`InternetFSHandler`: A handler for accessing documents via HTTP or FTP protocols.
* :ref:`MemoryFSHandler`: This handler allows you to access data stored in memory (such as bitmaps) as if they were regular files. See :ref:`MemoryFSHandler` for details.
URL is prefixed with memory:, e.g. ``"memory:myfile.htm"``.
* :ref:`wx.ArchiveFSHandler`: A handler for archives such as zip and
tar. URLs examples: ``"archive.zip#zip:filename"``,
``"archive.tar.gz#gzip:#tar:filename"``.
* :ref:`wx.FilterFSHandler`: A handler for compression schemes such as
gzip. URLs are in the form, e.g.: ``"document.ps.gz#gzip:"``.
* :ref:`wx.InternetFSHandler`: A handler for accessing documents via HTTP
or FTP protocols.
* :ref:`wx.MemoryFSHandler`: This handler allows you to access data
stored in memory (such as bitmaps) as if they were regular
files. See :ref:`wx.MemoryFSHandler` for details. URL is prefixed with
memory:, e.g. ``"memory:myfile.htm"``.
In addition, :ref:`FileSystem` itself can access local files.
@@ -74,11 +112,10 @@ In addition, :ref:`FileSystem` itself can access local files.
Initializing file system handlers
---------------------------------
Use :meth:`FileSystem.AddHandler` to initialize a handler, for example::
Use :meth:`wx.FileSystem.AddHandler` to initialize a handler, for
example::
def OnInit(self):
wx.FileSystem.AddHandler(wx.MemoryFSHandler())