ComboBox - almost working

This commit is contained in:
Vadim Lopatin 2014-12-15 16:34:13 +03:00
parent 0b67f637cc
commit 1d5b26ccdc
3 changed files with 117 additions and 7 deletions

View File

@ -1,3 +1,30 @@
// Written in the D programming language.
/**
This module contains Combo Box widgets implementation.
Synopsis:
----
import dlangui.widgets.combobox;
// creation of simple strings list
ComboBox box = new ComboBox("combo1", ["value 1"d, "value 2"d, "value 3"d]);
// select first item
box.selectedItemIndex = 0;
// get selected item text
println(box.text);
----
Copyright: Vadim Lopatin, 2014
License: Boost License 1.0
Authors: Vadim Lopatin, coolreader.org@gmail.com
*/
module dlangui.widgets.combobox;
import dlangui.widgets.widget;
@ -5,9 +32,11 @@ import dlangui.widgets.layouts;
import dlangui.widgets.editors;
import dlangui.widgets.lists;
import dlangui.widgets.controls;
import dlangui.widgets.popup;
private import std.algorithm;
/** Abstract ComboBox. */
class ComboBoxBase : HorizontalLayout, OnClickHandler {
protected Widget _body;
protected ImageButton _button;
@ -15,6 +44,9 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
protected bool _ownAdapter;
protected int _selectedItemIndex;
/** Handle item click. */
Signal!OnItemSelectedHandler onItemClickListener;
protected Widget createSelectedItemWidget() {
Widget res;
if (_adapter && _selectedItemIndex < _adapter.itemCount) {
@ -34,11 +66,15 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
}
@property void selectedItemIndex(int index) {
if (_selectedItemIndex == index)
return;
_selectedItemIndex = index;
if (onItemClickListener.assigned)
onItemClickListener(this, index);
}
override bool onClick(Widget source) {
// TODO
showPopup();
return true;
}
@ -48,17 +84,56 @@ class ComboBoxBase : HorizontalLayout, OnClickHandler {
return res;
}
protected ListWidget createPopup() {
ListWidget list = new ListWidget("POPUP_LIST");
list.adapter = _adapter;
list.selectedItemIndex = _selectedItemIndex;
return list;
}
protected PopupWidget _popup;
protected ListWidget _popupList;
protected void showPopup() {
_popupList = createPopup();
_popup = window.showPopup(_popupList, this, PopupAlign.Below | PopupAlign.FitAnchorSize);
_popup.flags = PopupFlags.CloseOnClickOutside;
_popup.styleId = "POPUP_MENU";
_popup.onPopupCloseListener = delegate (PopupWidget source) {
_popup = null;
_popupList = null;
};
_popupList.onItemSelectedListener = delegate(Widget source, int index) {
selectedItemIndex = index;
return true;
};
_popupList.onItemClickListener = delegate(Widget source, int index) {
selectedItemIndex = index;
if (_popup !is null)
_popup.close();
return true;
};
_popupList.setFocus();
}
this(string ID, ListAdapter adapter, bool ownAdapter = true) {
super(ID);
_adapter = adapter;
_ownAdapter = ownAdapter;
_body = createSelectedItemWidget();
_body.onClickListener = this;
_button = createButton();
//_body.state = State.Parent;
//focusable = true;
_button.focusable = false;
_body.focusable = true;
addChild(_body);
addChild(_button);
}
}
/** ComboBox with list of strings. */
class ComboBox : ComboBoxBase {
protected StringListAdapter _adapter;

View File

@ -20,6 +20,7 @@ module dlangui.widgets.lists;
import dlangui.widgets.widget;
import dlangui.widgets.controls;
import dlangui.core.signals;
/// list widget adapter provides items for list widgets
interface ListAdapter {
@ -155,8 +156,25 @@ class StringListAdapter : ListAdapter {
}
}
/// List
/** interface - slot for onItemSelectedListener */
interface OnItemSelectedHandler {
bool onItemSelected(Widget source, int itemIndex);
}
/** interface - slot for onItemClickListener */
interface OnItemClickHandler {
bool onItemClick(Widget source, int itemIndex);
}
/** List widget - shows content as hori*/
class ListWidget : WidgetGroup, OnScrollHandler {
/** Handle selection change. */
Signal!OnItemSelectedHandler onItemSelectedListener;
/** Handle item click. */
Signal!OnItemSelectedHandler onItemClickListener;
protected Orientation _orientation = Orientation.Vertical;
/// returns linear layout orientation (Vertical, Horizontal)
@property Orientation orientation() { return _orientation; }
@ -308,10 +326,14 @@ class ListWidget : WidgetGroup, OnScrollHandler {
/// override to handle change of selection
protected void selectionChanged(int index, int previouslySelectedItem = -1) {
if (onItemSelectedListener.assigned)
onItemSelectedListener(this, index);
}
/// override to handle mouse up on item
protected void itemClicked(int index) {
if (onItemClickListener.assigned)
onItemClickListener(this, index);
}
protected void updateSelectedItemFocus() {

View File

@ -22,6 +22,7 @@ module dlangui.widgets.popup;
import dlangui.widgets.widget;
import dlangui.widgets.layouts;
import dlangui.core.signals;
import dlangui.platforms.common.platform;
/// popup alignment option flags
@ -34,6 +35,8 @@ enum PopupAlign : uint {
Right = 4,
/// align to specified point
Point = 8,
/// if popup content size is less than anchor's size, increase it to anchor size
FitAnchorSize = 16,
}
struct PopupAnchor {
@ -49,17 +52,24 @@ enum PopupFlags : uint {
CloseOnClickOutside = 1,
}
/** interface - slot for onPopupCloseListener */
interface OnPopupCloseHandler {
void onPopupClosed(PopupWidget source);
}
/// popup widget container
class PopupWidget : LinearLayout {
protected PopupAnchor _anchor;
protected bool _modal;
protected uint _flags;
protected void delegate(PopupWidget popup) _onPopupCloseListener;
/** popup close signal */
Signal!OnPopupCloseHandler onPopupCloseListener;
//protected void delegate(PopupWidget popup) _onPopupCloseListener;
/// popup close listener (called right before closing)
@property void delegate(PopupWidget popup) onPopupCloseListener() { return _onPopupCloseListener; }
//@property void delegate(PopupWidget popup) onPopupCloseListener() { return _onPopupCloseListener; }
/// set popup close listener (to call right before closing)
@property PopupWidget onPopupCloseListener(void delegate(PopupWidget popup) listener) { _onPopupCloseListener = listener; return this; }
//@property PopupWidget onPopupCloseListener(void delegate(PopupWidget popup) listener) { _onPopupCloseListener = listener; return this; }
/// returns popup behavior flags (combination of PopupFlags)
@property uint flags() { return _flags; }
@ -84,8 +94,8 @@ class PopupWidget : LinearLayout {
/// just call on close listener
void onClose() {
if (_onPopupCloseListener !is null)
_onPopupCloseListener(this);
if (onPopupCloseListener.assigned)
onPopupCloseListener(this);
}
/// Set widget rectangle to specified value and layout widget contents. (Step 2 of two phase layout).
@ -124,6 +134,9 @@ class PopupWidget : LinearLayout {
r.left = anchorrc.right;
r.top = anchorrc.top;
}
if (anchor.alignment & PopupAlign.FitAnchorSize)
if (w < anchorrc.width)
w = anchorrc.width;
}
r.right = r.left + w;
r.bottom = r.top + h;