Dillo
|
This class handles selections, as well as activation of links, which is closely related. More...
#include <selection.hh>
Public Types | |
enum | { END_OF_WORD = 1 << 30 } |
enum | EventType { BUTTON_PRESS, BUTTON_RELEASE, BUTTON_MOTION } |
Public Member Functions | |
SelectionState () | |
~SelectionState () | |
void | setLayout (Layout *layout) |
void | reset () |
bool | buttonPress (Iterator *it, int charPos, int linkNo, EventButton *event) |
bool | buttonRelease (Iterator *it, int charPos, int linkNo, EventButton *event) |
bool | buttonMotion (Iterator *it, int charPos, int linkNo, EventMotion *event) |
bool | handleEvent (EventType eventType, Iterator *it, int charPos, int linkNo, MousePositionEvent *event) |
General form of dw::core::SelectionState::buttonPress, dw::core::SelectionState::buttonRelease and dw::core::SelectionState::buttonMotion. More... | |
Private Types | |
enum | { NONE, SELECTING, SELECTED } |
enum | { LINK_NONE, LINK_PRESSED } |
Private Member Functions | |
void | resetSelection () |
void | resetLink () |
void | switchLinkToSelection (Iterator *it, int charPos) |
This method is called when the user decides not to activate a link, but instead select text. More... | |
void | adjustSelection (Iterator *it, int charPos) |
This method is used by core::dw::SelectionState::buttonMotion and core::dw::SelectionState::buttonRelease, and changes the second limit of the already existing selection region. More... | |
void | highlight (bool fl, int dir) |
void | highlight0 (bool fl, DeepIterator *from, int fromChar, DeepIterator *to, int toChar, int dir) |
void | copy () |
Static Private Member Functions | |
static int | correctCharPos (DeepIterator *it, int charPos) |
This method deals especially with the case that a widget passes dw::core::SelectionState::END_OF_WORD. More... | |
Private Attributes | |
Layout * | layout |
enum dw::core::SelectionState:: { ... } | selectionState |
DeepIterator * | from |
DeepIterator * | to |
int | fromChar |
int | toChar |
enum dw::core::SelectionState:: { ... } | linkState |
int | linkButton |
DeepIterator * | link |
int | linkChar |
int | linkNumber |
This class handles selections, as well as activation of links, which is closely related.
dw::core::SelectionState is associated with dw::core::Layout. The selection state is controlled by "abstract events", which are sent by single widgets by calling one of the following methods:
The widget must construct simple iterators (dw::core::Iterator), which will be transferred to deep iterators (dw::core::DeepIterator), see below for more details. All event handling methods have the same signature, the arguments in detail are:
dw::core::Iterator *it | the iterator pointing on the item under the mouse pointer; this iterator must be created with dw::core::Content::SELECTION_CONTENT as mask |
int charPos | the exact (character) position within the iterator, |
int linkNo | if this item is associated with a link, its number (see dw::core::Layout::LinkReceiver), otherwise -1 |
dw::core::EventButton *event | the event itself; only the button is used |
Look also at dw::core::SelectionState::handleEvent, which may be useful in some circumstances.
In some cases, charPos would be difficult to determine. E.g., when the dw::Textblock widget decides that the user is pointing on a position at the end of an image (DwImage), it constructs a simple iterator pointing on this image widget. In a simple iterator, that fact that the pointer is at the end, would be represented by charPos == 1. But when transferring this simple iterator into an deep iterator, this simple iterator is discarded and instead the stack has an iterator pointing to text at the top. As a result, only the first letter of the ALT text would be copied.
To avoid this problem, widgets should in this case pass dw::core::SelectionState::END_OF_WORD as charPos, which is then automatically reduced to the actual length of the deep(!) iterator.
The return value is the same as in DwWidget event handling methods. I.e., in most cases, they should simply return it. The events dw::core::Layout::LinkReceiver::press, dw::core::Layout::LinkReceiver::release and dw::core::Layout::LinkReceiver::click (but not dw::core::Layout::LinkReceiver::enter) are emitted by these methods, so that widgets which let dw::core::SelectionState handle links, should only emit dw::core::Layout::LinkReceiver::enter for themselves.
Selection interferes with handling the activation of links, so the latter is also handled by the dw::core::SelectionState. Details are based on following guidelines:
It should be simple to select links and to start selection in links. The rule to distinguish between link activation and selection is that the selection starts as soon as the user leaves the link. (This is, IMO, a useful feature. Even after drag and drop has been implemented in dillo, this should be somehow preserved.)
The latter leads to a model with two states: the selection state and the link handling state.
The general selection works, for events not pointing on links, like this (numbers in parantheses after the event denote the button, "n" means arbitrary button):
The selected region is represented by two instances of dw::core::DeepIterator.
Links are handled by a different state machine:
Switching selection simply means that the selection state will eventually be SELECTED/SELECTING, with the original and the current position making up the selection region. This happens for button 1, events with buttons other than 1 do not affect selection at all.
dw::core::SelectionState::SelectionState | ( | ) |
References DBG_OBJ_CREATE, and layout.
dw::core::SelectionState::~SelectionState | ( | ) |
References DBG_OBJ_DELETE.
|
private |
This method is used by core::dw::SelectionState::buttonMotion and core::dw::SelectionState::buttonRelease, and changes the second limit of the already existing selection region.
References dw::core::DeepIterator::compareTo(), dw::core::DeepIterator::createVariant(), dw::core::DeepIterator::highlight(), and dw::core::HIGHLIGHT_SELECTION.
bool dw::core::SelectionState::buttonMotion | ( | Iterator * | it, |
int | charPos, | ||
int | linkNo, | ||
EventMotion * | event | ||
) |
bool dw::core::SelectionState::buttonPress | ( | Iterator * | it, |
int | charPos, | ||
int | linkNo, | ||
EventButton * | event | ||
) |
bool dw::core::SelectionState::buttonRelease | ( | Iterator * | it, |
int | charPos, | ||
int | linkNo, | ||
EventButton * | event | ||
) |
|
private |
References lout::misc::StringBuffer::append(), lout::misc::StringBuffer::appendNoCopy(), dw::core::Content::breakSpace, dw::core::DeepIterator::cloneDeepIterator(), dw::core::DeepIterator::compareTo(), lout::misc::StringBuffer::getChars(), dw::core::Iterator::getContent(), dw::core::DeepIterator::getContent(), dw::core::DeepIterator::getTopIterator(), layout, dw::core::DeepIterator::next(), dw::core::Content::space, strndup(), dw::core::Content::text, and dw::core::Content::type.
|
staticprivate |
This method deals especially with the case that a widget passes dw::core::SelectionState::END_OF_WORD.
References dw::core::Iterator::getContent(), dw::core::DeepIterator::getTopIterator(), lout::misc::min(), dw::core::Content::text, and dw::core::Content::type.
bool dw::core::SelectionState::handleEvent | ( | EventType | eventType, |
Iterator * | it, | ||
int | charPos, | ||
int | linkNo, | ||
MousePositionEvent * | event | ||
) |
General form of dw::core::SelectionState::buttonPress, dw::core::SelectionState::buttonRelease and dw::core::SelectionState::buttonMotion.
References lout::misc::assertNotReached().
Referenced by dw::core::Widget::selectionHandleEvent().
|
inlineprivate |
References highlight0().
|
private |
References dw::core::DeepIterator::cloneDeepIterator(), dw::core::DeepIterator::compareTo(), dw::core::DeepIterator::getContent(), dw::core::DeepIterator::highlight(), dw::core::HIGHLIGHT_SELECTION, dw::core::DeepIterator::next(), dw::core::Content::text, dw::core::Content::type, and dw::core::DeepIterator::unhighlight().
Referenced by highlight().
void dw::core::SelectionState::reset | ( | ) |
|
private |
|
private |
|
private |
This method is called when the user decides not to activate a link, but instead select text.
|
private |
|
private |
|
private |
Referenced by setLayout().
|
private |
|
private |
|
private |
|
private |
enum { ... } dw::core::SelectionState::linkState |
enum { ... } dw::core::SelectionState::selectionState |
|
private |
|
private |