1 // Written in the D programming language.
2 
3 /**
4 This module contains definition for status line control.
5 
6 Status line is usually shown in the bottom of window, and shows status of app.
7 
8 Contains one or more text and/or icon items
9 
10 Synopsis:
11 
12 ----
13 import dlangui.widgets.statusline;
14 
15 ----
16 
17 Copyright: Vadim Lopatin, 2015
18 License:   Boost License 1.0
19 Authors:   Vadim Lopatin, coolreader.org@gmail.com
20 */
21 module dlangui.widgets.statusline;
22 
23 import dlangui.widgets.layouts;
24 import dlangui.widgets.controls;
25 import dlangui.widgets.editors;
26 
27 class StatusLinePanelBase : HorizontalLayout {
28     this(string ID) {
29         super(ID);
30     }
31 }
32 
33 class StatusLineTextPanel : StatusLinePanelBase {
34     protected TextWidget _text;
35     this(string ID) {
36         super(ID);
37         _text = new TextWidget(null, ""d);
38         addChild(_text);
39     }
40     /// returns widget content text (override to support this)
41     override @property dstring text() const { return _text.text; }
42     /// sets widget content text (override to support this)
43     override @property Widget text(dstring s) { _text.text = s; return this; }
44     /// sets widget content text (override to support this)
45     override @property Widget text(UIString s) { _text.text = s; return this; }
46 }
47 
48 class StatusLineIconPanel : StatusLinePanelBase {
49     protected ImageWidget _icon;
50     this(string ID) {
51         super(ID);
52         _icon = new ImageWidget(null);
53         addChild(_icon);
54     }
55     @property string iconId() {
56         return _icon.drawableId;
57     }
58     @property void iconId(string icon) {
59         _icon.drawableId = icon;
60     }
61 }
62 
63 class StatusLineTextAndIconPanel : StatusLineTextPanel {
64     protected ImageWidget _icon;
65     this(string ID) {
66         super(ID);
67         _icon = new ImageWidget(null);
68         _icon.minWidth = WIDGET_STYLE_CONSOLE ? 1 : 20;
69         _icon.minHeight = WIDGET_STYLE_CONSOLE ? 1 : 20;
70         _icon.alignment = Align.Center;
71         addChild(_icon);
72     }
73     @property string iconId() {
74         return _icon.drawableId;
75     }
76     @property void iconId(string icon) {
77         _icon.drawableId = icon;
78     }
79 }
80 
81 class StatusLineBackgroundOperationPanel : StatusLineTextAndIconPanel {
82     this(string ID) {
83         super(ID);
84         visibility = Visibility.Gone;
85     }
86     protected uint animationProgress;
87     /// show / update / animate background operation status; when both parameters are nulls, hide background op status panel
88     void setBackgroundOperationStatus(string icon, dstring statusText) {
89         if (icon || statusText) {
90             visibility = Visibility.Visible;
91             text = statusText;
92             iconId = icon;
93             animationProgress = (animationProgress + 30) % 512;
94             uint a = animationProgress;
95             if (a >= 256)
96                 a = 512 - a;
97             _icon.backgroundColor((a << 24) | (0x00FF00));
98         } else {
99             visibility = Visibility.Gone;
100         }
101     }
102 }
103 
104 class StatusLineEditorStatePanel : StatusLineTextPanel {
105     EditorStateInfo _editorState;
106 
107     this(string ID = "statusLineEditorStateLabel") {
108         super(ID);
109         _text.alignment = Align.VCenter | Align.Right;
110         //_text.backgroundColor = 0x80FF0000;
111         //backgroundColor = 0x8000FF00;
112         updateSize();
113         visibility = Visibility.Gone;
114     }
115 
116     dstring makeStateString() {
117         if (!_editorState.active)
118             return null;
119         import std.string : format;
120         return "%d : %d    ch=0x%05x    %s  "d.format(_editorState.line, _editorState.col, _editorState.character, _editorState.replaceMode ? "OVR"d : "INS"d);
121     }
122 
123     private void updateSize() {
124         FontRef fnt = font;
125         Point sz = fnt.textSize("  ch=0x00000    000000 : 000    INS  "d);
126         _text.minWidth = sz.x;
127     }
128 
129     /// handle theme change: e.g. reload some themed resources
130     override void onThemeChanged() {
131         super.onThemeChanged();
132         updateSize();
133     }
134 
135     void setState(Widget source, ref EditorStateInfo editorState) {
136         if (editorState != _editorState) {
137             _editorState = editorState;
138             text = makeStateString();
139             Visibility newVisibility = _editorState.active ? Visibility.Visible : Visibility.Gone;
140             if (newVisibility != visibility)
141                 visibility = newVisibility;
142         }
143     }
144 }
145 
146 /// Status line control
147 class StatusLine : HorizontalLayout, EditorStateListener {
148     protected TextWidget _defStatus;
149     protected StatusLineBackgroundOperationPanel _backgroundOperationPanel;
150     protected StatusLineEditorStatePanel _editorStatePanel;
151     this() {
152         super("STATUS_LINE");
153         styleId = STYLE_STATUS_LINE;
154         initialize();
155     }
156     void initialize() {
157         _defStatus = new TextWidget("STATUS_LINE_TEXT");
158         _defStatus.layoutWidth(FILL_PARENT);
159         _defStatus.text = " "d;
160         addChild(_defStatus);
161         _backgroundOperationPanel = new StatusLineBackgroundOperationPanel("BACKGROUND_OP_STATUS");
162         _editorStatePanel = new StatusLineEditorStatePanel("EDITOR_STATE_PANEL");
163         addChild(_backgroundOperationPanel);
164         addChild(_editorStatePanel);
165     }
166     /// set text to show in status line in specific panel
167     void setStatusText(string itemId, dstring value) {
168         _defStatus.text = value;
169     }
170     /// set text to show in status line
171     void setStatusText(dstring value) {
172         setStatusText(null, value);
173     }
174     /// show / update / animate background operation status; when both parameters are nulls, hide background op status panel
175     void setBackgroundOperationStatus(string icon, dstring statusText = null) {
176         _backgroundOperationPanel.setBackgroundOperationStatus(icon, statusText);
177     }
178 
179     /// EditorStateListener implementation
180     override void onEditorStateUpdate(Widget source, ref EditorStateInfo editorState) {
181         _editorStatePanel.setState(source, editorState);
182     }
183 
184     void hideEditorState() {
185         EditorStateInfo editorState;
186         _editorStatePanel.setState(null, editorState);
187     }
188 }