mirror of https://github.com/buggins/dlangui.git
actions state requests, part 2
This commit is contained in:
parent
7564129b42
commit
bf79159d39
|
@ -60,9 +60,13 @@ class ActionState {
|
||||||
ActionState clone() const {
|
ActionState clone() const {
|
||||||
return new ActionState(enabled, visible, checked);
|
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
|
/// action is
|
||||||
__gshared const(ActionState) ACTION_STATE_DEFAULT_ENABLED;
|
__gshared const(ActionState) ACTION_STATE_DEFAULT_ENABLED;
|
||||||
|
@ -98,39 +102,30 @@ class Action {
|
||||||
/// optional object parameter
|
/// optional object parameter
|
||||||
protected Object _objectParam;
|
protected Object _objectParam;
|
||||||
|
|
||||||
|
protected ActionState _state;
|
||||||
|
|
||||||
protected ActionState _defaultState;
|
protected ActionState _defaultState;
|
||||||
|
|
||||||
/// default state for action if action state lookup failed
|
/// default state for action if action state lookup failed
|
||||||
@property const(ActionState) defaultState() const { return _defaultState ? _defaultState : ACTION_STATE_DEFAULT_ENABLED; }
|
@property const(ActionState) defaultState() const { return _defaultState ? _defaultState : ACTION_STATE_DEFAULT_ENABLED; }
|
||||||
|
|
||||||
/// default state for action if action state lookup failed
|
/// default state for action if action state lookup failed
|
||||||
@property Action defaultState(ActionState s) { _defaultState = s; return this; }
|
@property Action defaultState(ActionState s) { _defaultState = s; return this; }
|
||||||
|
/// action state
|
||||||
/// returns true if action is state request
|
@property const(ActionState) state() const { return _state ? _state : (_defaultState ? _defaultState : ACTION_STATE_DEFAULT_ENABLED); }
|
||||||
@property bool isStateRequest() const {
|
/// update action state (for non-const action)
|
||||||
return id == ACTION_ID_STATE_REQUEST;
|
@property Action state(const ActionState s) {
|
||||||
}
|
if (_state != s)
|
||||||
|
_state = s.clone();
|
||||||
/// 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;
|
return this;
|
||||||
}
|
}
|
||||||
/// create state request action for current action
|
/// update action state (can be changed even for const objects)
|
||||||
Action createStateRequest() {
|
@property const(Action) state(const ActionState s) const {
|
||||||
return (new Action(ACTION_ID_STATE_REQUEST)).longParam(_id).objectParam(defaultState.clone());
|
if (_state != s) {
|
||||||
|
// hack
|
||||||
|
Action nonConstThis = cast(Action) this;
|
||||||
|
nonConstThis._state = s.clone();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// returns optional string parameter
|
/// returns optional string parameter
|
||||||
|
@ -169,6 +164,8 @@ class Action {
|
||||||
_id = a._id;
|
_id = a._id;
|
||||||
_label = a._label;
|
_label = a._label;
|
||||||
_iconId = a._iconId;
|
_iconId = a._iconId;
|
||||||
|
_state = a._state.clone();
|
||||||
|
_defaultState = a._defaultState.clone();
|
||||||
_accelerators.length = a._accelerators.length;
|
_accelerators.length = a._accelerators.length;
|
||||||
for(int i = 0; i < _accelerators.length; i++)
|
for(int i = 0; i < _accelerators.length; i++)
|
||||||
_accelerators[i] = a._accelerators[i];
|
_accelerators[i] = a._accelerators[i];
|
||||||
|
|
|
@ -364,6 +364,7 @@ class Window {
|
||||||
}
|
}
|
||||||
if (animationActive)
|
if (animationActive)
|
||||||
scheduleAnimation();
|
scheduleAnimation();
|
||||||
|
_actionsUpdateRequested = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// after drawing, call to schedule redraw if animation is active
|
/// after drawing, call to schedule redraw if animation is active
|
||||||
|
@ -401,6 +402,8 @@ class Window {
|
||||||
newFocus.setState(State.Focused);
|
newFocus.setState(State.Focused);
|
||||||
}
|
}
|
||||||
_focusedWidget = newFocus;
|
_focusedWidget = newFocus;
|
||||||
|
// after focus change, ask for actions update automatically
|
||||||
|
requestActionsUpdate();
|
||||||
}
|
}
|
||||||
return _focusedWidget;
|
return _focusedWidget;
|
||||||
}
|
}
|
||||||
|
@ -611,6 +614,38 @@ class Window {
|
||||||
return false;
|
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)
|
/// post event to handle in UI thread (this method can be used from background thread)
|
||||||
void postEvent(CustomEvent event) {
|
void postEvent(CustomEvent event) {
|
||||||
// override to post event into window message queue
|
// override to post event into window message queue
|
||||||
|
@ -833,6 +868,16 @@ class Window {
|
||||||
/// close window
|
/// close window
|
||||||
abstract void close();
|
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
|
/// 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) {
|
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);
|
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; }
|
@property void action(const Action action) { _action = action.clone; }
|
||||||
/// action to emit on click
|
/// action to emit on click
|
||||||
@property void action(Action action) { _action = action; }
|
@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;
|
protected bool _focusGroup;
|
||||||
/*****************************************
|
/*****************************************
|
||||||
|
@ -906,6 +923,10 @@ class Widget {
|
||||||
bool handleAction(const Action a) {
|
bool handleAction(const Action a) {
|
||||||
return false;
|
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
|
/// call to dispatch action
|
||||||
bool dispatchAction(const Action a) {
|
bool dispatchAction(const Action a) {
|
||||||
|
|
Loading…
Reference in New Issue