Commit 16fd9c9b authored by twanvl's avatar twanvl

Multiple choice box kept open until mouse out

parent 44ec3bf3
......@@ -40,6 +40,10 @@ class DropDownHider : public wxEvtHandler {
list.hide(false);
if (nh) nh->ProcessEvent(ev);
return false;
} else if (t == wxEVT_MOTION) {
// send along all motion events
list.ProcessEvent(ev);
return wxEvtHandler::ProcessEvent(ev);
} else {
// if (t !=10093 && t !=10098 && t !=10097 && t !=10099 && t !=10004 && t !=10062
// && t !=10025 && t !=10035 && t !=10034 && t !=10036 && t !=10042 && t !=10119)
......@@ -64,7 +68,8 @@ DropDownList::DropDownList(Window* parent, bool is_submenu, ValueViewer* viewer)
, open_sub_menu(nullptr)
, parent_menu(nullptr)
, viewer(viewer)
, hider(is_submenu ? nullptr : new DropDownHider(*this))
, hider (is_submenu ? nullptr : new DropDownHider(*this))
, hider2(is_submenu ? nullptr : new DropDownHider(*this))
{
if (is_submenu) {
parent_menu = &dynamic_cast<DropDownList&>(*GetParent());
......@@ -80,6 +85,7 @@ DropDownList::DropDownList(Window* parent, bool is_submenu, ValueViewer* viewer)
DropDownList::~DropDownList() {
realHide(); // restore event handler before deleting it
delete hider;
delete hider2;
}
void DropDownList::show(bool in_place, wxPoint pos) {
......@@ -128,8 +134,9 @@ void DropDownList::show(bool in_place, wxPoint pos) {
Position(pos, wxSize(0, parent_height));
// set event handler
if (hider) {
Window* parent = wxGetTopLevelParent(GetParent());
parent->PushEventHandler(hider);
assert(hider2);
wxGetTopLevelParent(GetParent())->PushEventHandler(hider);
GetParent() ->PushEventHandler(hider2);
}
// show
if (selected_item == NO_SELECTION && itemCount() > 0) selected_item = 0; // select first item by default
......@@ -139,15 +146,21 @@ void DropDownList::show(bool in_place, wxPoint pos) {
redrawArrowOnParent();
}
void DropDownList::hide(bool event) {
void DropDownList::hide(bool event, bool allow_veto) {
// send event
if (event && selected_item != NO_SELECTION && itemEnabled(selected_item)) {
bool close = select(selected_item);
if (allow_veto && !close) {
Refresh(false);
return;
}
}
// hide root
DropDownList* root = this;
while (root->parent_menu) {
root = root->parent_menu;
}
root->realHide();
// send event
if (event && selected_item != NO_SELECTION && itemEnabled(selected_item)) select(selected_item);
}
void DropDownList::realHide() {
......@@ -160,8 +173,8 @@ void DropDownList::realHide() {
} else {
redrawArrowOnParent();
// disconnect event handler
Window* parent = wxGetTopLevelParent(GetParent());
parent->RemoveEventHandler(hider);
GetParent() ->RemoveEventHandler(hider2);
wxGetTopLevelParent(GetParent())->RemoveEventHandler(hider);
}
}
......@@ -348,6 +361,11 @@ bool DropDownList::onCharInParent(wxKeyEvent& ev) {
}
break;
case WXK_RETURN:
if (!showSubMenu() && (selected_item == NO_SELECTION || itemEnabled(selected_item))) {
hide(true, false); // don't veto; always close
}
break;
case WXK_SPACE:
if (!showSubMenu() && (selected_item == NO_SELECTION || itemEnabled(selected_item))) {
hide(true);
}
......
......@@ -31,7 +31,7 @@ class DropDownList : public wxPopupWindow {
/** if in_place, then shows the list at the position pos */
void show(bool in_place, wxPoint pos);
/// Close the list, optionally send an onSelect event
void hide(bool event);
void hide(bool event, bool allow_veto = true);
// --------------------------------------------------- : Parent control
/// Takes all keyboard events from a FieldEditor
......@@ -48,7 +48,9 @@ class DropDownList : public wxPopupWindow {
static const size_t NO_SELECTION = (size_t)-1;
/// Signal that the list is closed and something is selected
virtual void select(size_t selection) = 0;
/** Returns true if the event was handled and the list should be hidden,
* false keeps the list open. */
virtual bool select(size_t selection) = 0;
/// When the list is being opened, what should be selected?
virtual size_t selection() const = 0;
......@@ -86,7 +88,7 @@ class DropDownList : public wxPopupWindow {
DropDownList* open_sub_menu; ///< The sub menu that is currently shown, if any
DropDownList* parent_menu; ///< The parent menu, only applies to sub menus
ValueViewer* viewer; ///< The parent viewer object (optional)
DropDownHider* hider; ///< Class to hide this window when we lose focus
DropDownHider* hider, *hider2; ///< Class to hide this window when we lose focus
// --------------------------------------------------- : Events
DECLARE_EVENT_TABLE();
......@@ -94,7 +96,9 @@ class DropDownList : public wxPopupWindow {
void onPaint(wxPaintEvent&);
void onLeftDown(wxMouseEvent&);
void onLeftUp (wxMouseEvent&);
void onMotion (wxMouseEvent&);
protected:
virtual void onMotion(wxMouseEvent&); // allow override
private:
// --------------------------------------------------- : Privates
......
......@@ -227,13 +227,14 @@ void DropDownChoiceList::onShow() {
generateThumbnailImages();
}
void DropDownChoiceList::select(size_t item) {
bool DropDownChoiceList::select(size_t item) {
if (isFieldDefault(item)) {
dynamic_cast<ChoiceValueEditor&>(cve).change( Defaultable<String>() );
} else {
ChoiceField::ChoiceP choice = getChoice(item);
dynamic_cast<ChoiceValueEditor&>(cve).change( field().choices->choiceName(choice->first_id) );
}
return true;
}
size_t DropDownChoiceList::selection() const {
......@@ -278,8 +279,6 @@ ChoiceValueEditor::~ChoiceValueEditor() {
}
bool ChoiceValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
//HACK TODO REMOVEME
//thumbnail_thread.abortAll();
return drop_down->onMouseInParent(ev, style().popup_style == POPUP_DROPDOWN_IN_PLACE && !nativeLook());
}
bool ChoiceValueEditor::onChar(wxKeyEvent& ev) {
......
......@@ -95,7 +95,7 @@ class DropDownChoiceList : public DropDownChoiceListBase {
protected:
virtual void onShow();
virtual void select(size_t item);
virtual bool select(size_t item);
virtual size_t selection() const;
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const;
};
......
......@@ -27,7 +27,7 @@ class DropDownColorList : public DropDownList {
virtual String itemText(size_t item) const;
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
virtual void select(size_t item);
virtual bool select(size_t item);
virtual size_t selection() const;
private:
......@@ -112,7 +112,7 @@ size_t DropDownColorList::selection() const {
}
return selection;
}
void DropDownColorList::select(size_t item) {
bool DropDownColorList::select(size_t item) {
if (isDefault(item)) {
cve.change( Defaultable<Color>());
} else if (isCustom(item)) {
......@@ -120,6 +120,7 @@ void DropDownColorList::select(size_t item) {
} else {
cve.change(field().choices[item - hasDefault()]->color);
}
return true;
}
// ----------------------------------------------------------------------------- : ColorValueEditor
......
......@@ -19,20 +19,26 @@ class DropDownMultipleChoiceList : public DropDownChoiceListBase {
DropDownMultipleChoiceList(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group);
protected:
virtual void select(size_t item);
virtual void onShow();
virtual bool select(size_t item);
virtual size_t selection() const;
virtual DropDownList* createSubMenu(ChoiceField::ChoiceP group) const;
virtual void drawIcon(DC& dc, int x, int y, size_t item, bool selected) const;
virtual void onMotion(wxMouseEvent&);
private:
bool kept_open; ///< Was the list kept open after selecting a choice, if so, be eager to close it
};
DropDownMultipleChoiceList::DropDownMultipleChoiceList
(Window* parent, bool is_submenu, ValueViewer& cve, ChoiceField::ChoiceP group)
: DropDownChoiceListBase(parent, is_submenu, cve, group)
, kept_open(false)
{
icon_size.width += 16;
}
void DropDownMultipleChoiceList::select(size_t item) {
bool DropDownMultipleChoiceList::select(size_t item) {
MultipleChoiceValueEditor& mcve = dynamic_cast<MultipleChoiceValueEditor&>(cve);
if (isFieldDefault(item)) {
mcve.toggleDefault();
......@@ -40,6 +46,10 @@ void DropDownMultipleChoiceList::select(size_t item) {
ChoiceField::ChoiceP choice = getChoice(item);
mcve.toggle(choice->first_id);
}
// keep the box open
DropDownChoiceListBase::onShow(); // update 'enabled'
kept_open = true;
return false;
}
void DropDownMultipleChoiceList::drawIcon(DC& dc, int x, int y, size_t item, bool selected) const {
......@@ -67,17 +77,31 @@ void DropDownMultipleChoiceList::drawIcon(DC& dc, int x, int y, size_t item, boo
DropDownChoiceListBase::drawIcon(dc, x + 16, y, item, selected);
}
size_t DropDownMultipleChoiceList::selection() const {
void DropDownMultipleChoiceList::onShow() {
DropDownChoiceListBase::onShow();
// we need thumbnail images soon
const_cast<DropDownMultipleChoiceList*>(this)->generateThumbnailImages();
// we don't know the selection
return NO_SELECTION;
kept_open = false;
}
size_t DropDownMultipleChoiceList::selection() const {
return NO_SELECTION; // we don't know the selection
}
DropDownList* DropDownMultipleChoiceList::createSubMenu(ChoiceField::ChoiceP group) const {
return new DropDownMultipleChoiceList(const_cast<DropDownMultipleChoiceList*>(this), true, cve, group);
}
void DropDownMultipleChoiceList::onMotion(wxMouseEvent& ev) {
if (kept_open) {
wxSize cs = GetClientSize();
if (ev.GetX() < 0 || ev.GetY() < 0 || ev.GetX() >= cs.x || ev.GetY() >= cs.y) {
hide(false); // outside box; hide it
}
}
DropDownChoiceListBase::onMotion(ev);
}
// ----------------------------------------------------------------------------- : MultipleChoiceValueEditor
IMPLEMENT_VALUE_EDITOR(MultipleChoice) {}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment