mirror of https://github.com/buggins/dlangui.git
actions state requests, part 2
This commit is contained in:
parent
7564129b42
commit
bf79159d39
|
@ -60,10 +60,14 @@ class ActionState {
|
|||
ActionState clone() const {
|
||||
return new ActionState(enabled, visible, checked);
|
||||
}
|
||||
override bool opEquals(Object obj) {
|
||||
if (auto other = cast(ActionState)obj) {
|
||||
return enabled == other.enabled && visible == other.visible && checked == other.checked;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
immutable ACTION_ID_STATE_REQUEST = -1;
|
||||
|
||||
/// action is
|
||||
__gshared const(ActionState) ACTION_STATE_DEFAULT_ENABLED;
|
||||
__gshared const(ActionState) ACTION_STATE_DEFAULT_DISABLE;
|
||||
|
@ -98,39 +102,30 @@ class Action {
|
|||
/// optional object parameter
|
||||
protected Object _objectParam;
|
||||
|
||||
protected ActionState _state;
|
||||
|
||||
protected ActionState _defaultState;
|
||||
|
||||
/// default state for action if action state lookup failed
|
||||
@property const(ActionState) defaultState() const { return _defaultState ? _defaultState : ACTION_STATE_DEFAULT_ENABLED; }
|
||||
|
||||
/// default state for action if action state lookup failed
|
||||
@property Action defaultState(ActionState s) { _defaultState = s; return this; }
|
||||
|
||||
/// returns true if action is state request
|
||||
@property bool isStateRequest() const {
|
||||
return id == ACTION_ID_STATE_REQUEST;
|
||||
/// action state
|
||||
@property const(ActionState) state() const { return _state ? _state : (_defaultState ? _defaultState : ACTION_STATE_DEFAULT_ENABLED); }
|
||||
/// update action state (for non-const action)
|
||||
@property Action state(const ActionState s) {
|
||||
if (_state != s)
|
||||
_state = s.clone();
|
||||
return this;
|
||||
}
|
||||
|
||||
/// if this action is request of UI state for another action, returns ID of action state is requested for
|
||||
@property int requestedActionId() const {
|
||||
return isStateRequest ? cast(int)_longParam : 0;
|
||||
}
|
||||
/// if this action is request of UI state for another action, returns state (default if not changed while request handling by UI components)
|
||||
@property const(ActionState) requestedActionState() const {
|
||||
assert(isStateRequest);
|
||||
return cast(ActionState)_objectParam;
|
||||
}
|
||||
/// if this action is request of UI state for another action, returns state (default if not changed while request handling by UI components)
|
||||
@property const(Action) requestedActionState(ActionState s) const {
|
||||
// hack: it's ok to replace action state in const ACTION_ID_STATE_REQUEST action
|
||||
assert(isStateRequest);
|
||||
Action nonconstThis = cast(Action)this;
|
||||
nonconstThis._objectParam = cast(Object)s.clone();
|
||||
return this;
|
||||
}
|
||||
/// create state request action for current action
|
||||
Action createStateRequest() {
|
||||
return (new Action(ACTION_ID_STATE_REQUEST)).longParam(_id).objectParam(defaultState.clone());
|
||||
/// update action state (can be changed even for const objects)
|
||||
@property const(Action) state(const ActionState s) const {
|
||||
if (_state != s) {
|
||||
// hack
|
||||
Action nonConstThis = cast(Action) this;
|
||||
nonConstThis._state = s.clone();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// returns optional string parameter
|
||||
|
@ -169,6 +164,8 @@ class Action {
|
|||
_id = a._id;
|
||||
_label = a._label;
|
||||
_iconId = a._iconId;
|
||||
_state = a._state.clone();
|
||||
_defaultState = a._defaultState.clone();
|
||||
_accelerators.length = a._accelerators.length;
|
||||
for(int i = 0; i < _accelerators.length; i++)
|
||||
_accelerators[i] = a._accelerators[i];
|
||||
|
|
|
@ -364,6 +364,7 @@ class Window {
|
|||
}
|
||||
if (animationActive)
|
||||
scheduleAnimation();
|
||||
_actionsUpdateRequested = false;
|
||||
}
|
||||
|
||||
/// after drawing, call to schedule redraw if animation is active
|
||||
|
@ -401,6 +402,8 @@ class Window {
|
|||
newFocus.setState(State.Focused);
|
||||
}
|
||||
_focusedWidget = newFocus;
|
||||
// after focus change, ask for actions update automatically
|
||||
requestActionsUpdate();
|
||||
}
|
||||
return _focusedWidget;
|
||||
}
|
||||
|
@ -611,6 +614,38 @@ class Window {
|
|||
return false;
|
||||
}
|
||||
|
||||
/// dispatch action to main widget
|
||||
bool dispatchActionStateRequest(const Action action, Widget sourceWidget = null) {
|
||||
// try to handle by source widget
|
||||
if(sourceWidget && isChild(sourceWidget)) {
|
||||
if (sourceWidget.handleActionStateRequest(action))
|
||||
return true;
|
||||
sourceWidget = sourceWidget.parent;
|
||||
}
|
||||
Widget focus = focusedWidget;
|
||||
// then offer action to focused widget
|
||||
if (focus && isChild(focus)) {
|
||||
if (focus.handleActionStateRequest(action))
|
||||
return true;
|
||||
focus = focus.parent;
|
||||
}
|
||||
// then offer to parent chain of source widget
|
||||
while (sourceWidget && isChild(sourceWidget)) {
|
||||
if (sourceWidget.handleActionStateRequest(action))
|
||||
return true;
|
||||
sourceWidget = sourceWidget.parent;
|
||||
}
|
||||
// then offer to parent chain of focused widget
|
||||
while (focus && isChild(focus)) {
|
||||
if (focus.handleActionStateRequest(action))
|
||||
return true;
|
||||
focus = focus.parent;
|
||||
}
|
||||
if (_mainWidget)
|
||||
return _mainWidget.handleActionStateRequest(action);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// post event to handle in UI thread (this method can be used from background thread)
|
||||
void postEvent(CustomEvent event) {
|
||||
// override to post event into window message queue
|
||||
|
@ -833,6 +868,16 @@ class Window {
|
|||
/// close window
|
||||
abstract void close();
|
||||
|
||||
protected bool _actionsUpdateRequested;
|
||||
/// set action update request flag, will be cleared after redraw
|
||||
void requestActionsUpdate() {
|
||||
_actionsUpdateRequested = true;
|
||||
}
|
||||
|
||||
@property bool actionsUpdateRequested() {
|
||||
return _actionsUpdateRequested;
|
||||
}
|
||||
|
||||
/// Show message box with specified title and message
|
||||
void showMessageBox(UIString title, UIString message, const (Action)[] actions = [ACTION_OK], int defaultActionIndex = 0, bool delegate(const Action result) handler = null) {
|
||||
MessageBox dlg = new MessageBox(title, message, this, actions, defaultActionIndex, handler);
|
||||
|
|
|
@ -626,7 +626,24 @@ class Widget {
|
|||
@property void action(const Action action) { _action = action.clone; }
|
||||
/// action to emit on click
|
||||
@property void action(Action action) { _action = action; }
|
||||
|
||||
/// ask for update state of some action (unles force=true, checks window flag
|
||||
void updateActionState(Action a, bool force = false) {
|
||||
if (Window w = window) {
|
||||
if (!force && !w.actionsUpdateRequested())
|
||||
return;
|
||||
if (w.dispatchActionStateRequest(a, this)) {
|
||||
// state is updated
|
||||
} else {
|
||||
a.state = a.defaultState;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// call to update state for action (if action is assigned for widget)
|
||||
void updateActionState(bool force = false) {
|
||||
if (!_action)
|
||||
return;
|
||||
updateActionState(_action, force);
|
||||
}
|
||||
|
||||
protected bool _focusGroup;
|
||||
/*****************************************
|
||||
|
@ -906,6 +923,10 @@ class Widget {
|
|||
bool handleAction(const Action a) {
|
||||
return false;
|
||||
}
|
||||
/// override to handle specific actions state (e.g. change enabled state for supported actions)
|
||||
bool handleActionStateRequest(const Action a) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// call to dispatch action
|
||||
bool dispatchAction(const Action a) {
|
||||
|
|
Loading…
Reference in New Issue