1 #include "stdafx.h"
4
6 {
7 /*
8
9 BEHAVIOR: tabs
10 goal: Implementation of the tabs: stacked panels switchable by tabs in tab strip
11 COMMENTS:
12 <div style="behavior:tabs">
13 <ul> <!-- our tab strip, can be placed on any side of tab container. -->
14 <li panel="panel-id1" selected >tab1 caption</li>
15 <li panel="panel-id2">tab2 caption</li>
16 </ul>
17 <div name="panel-id1" > first panel content </div>
18 <div name="panel-id2"> second panel content </div>
19 </div>
20 SAMPLE:
21 See: samples/behaviors/tabs.htm
22 */
23
24 struct tabs:
public event_handler, behavior_factory
25 {
26 // ctor
28 behavior_factory("tabs")
29 {}
30
32 {
38 return true;
39 }
40
41 // the only behavior_factory method:
43
45 {
46 dom::element tabs_el = he;
//:root below matches the element we use to start lookup from. 48
50 // find panel we need to show by default
51 dom::element panel_el = tabs_el.
find_first(
":root>[name=\"%s\"],:root>[id=\"%s\"]", aux::w2a(pname).c_str(), aux::w2a(pname).c_str());
53 {
54 assert(false); // what a ...!, panel="somename" without matching name="somename"
55 return;
56 }
57
62
63 //tabs_el.start_timer(1000, (void*) 12345);
64
65 }
66
67 /*virtual bool on_timer (HELEMENT he, UINT_PTR timerId )
68 {
69 ::MessageBeep(MB_ICONASTERISK);
70 return true;
71 }*/
72
74 {
76 return false;
77
80
82 return false;
83
84 //el here is a <element panel="panel-id1">tab1 caption</element>
85 //and we've got here MOUSE_DOWN somewhere on it.
86
88 }
89
91 {
93 }
94
95 #ifdef WINDOWS
96 virtual bool on_key(
HELEMENT he,
HELEMENT target, UINT event_type, UINT code, UINT keyboardStates )
97 {
99 return FALSE; // we are handling only KEY_DOWN here
100
103
104 switch( code )
105 {
109 break;
114 }
115 return FALSE;
116 }
117 #endif
118
120 {
122 {
125 {
126 assert(false); // target is not a tab here.
127 return TRUE;
128 }
131 return TRUE;
132 }
133 return FALSE;
134 }
135
136 // select
138 {
140 // already selected, nothing to do...
141 return true; // but we've handled it.
142
143 //find currently selected element (tab and panel) and remove "selected" from them
146
147 // find new tab and panel
149 dom::element panel_el = tabs_el.
find_first(
":root>[name=\"%s\"],:root>[id=\"%s\"]", aux::w2a(pname).c_str(), aux::w2a(pname).c_str());
150
152 {
153 assert(false); // panel="somename" without matching name="somename"
154 return true;
155 }
156
158 {
159 prev_panel_el.
set_attribute(
"selected", 0);
// remove selected attribute - just in case somone is using attribute selectors 161 }
163 {
164 prev_tab_el.
set_attribute(
"selected", 0);
// remove selected attribute 166 }
167
168 panel_el.
set_attribute(
"selected", WSTR(
""));
// set selected attribute (empty) 170
171 tab_el.
set_attribute(
"selected", WSTR(
""));
// set selected attribute (empty) 173
174 // notify all parties involved
178 // NOTE #1: these event will bubble from panel elements up to the root so panel itself, tabs ctl, its parent, etc.
179 // will receive these notifications. Handle them if you need to change UI dependent from current tab.
180 // NOTE #2: while handling this event in:
181 // virtual bool on_event (HELEMENT he, HELEMENT target, BEHAVIOR_EVENTS type, UINT reason ),
182 // HELEMENT target is the panel element being collapsed/expanded
183
184 return true;
185 }
186
187 // select next/prev/first/last tab
189 {
190
191 // find new tab
192
194
195 int rdirection = direction;
196
197 switch( direction )
198 {
199 case -2: new_tab_el = tab_el.
first_sibling(); rdirection = +1;
break;
202 case +2: new_tab_el = tab_el.
last_sibling(); rdirection = -1;
break;
203 default: assert(false); return false;
204 }
205
206 if( !new_tab_el.
is_valid() || new_tab_el.
get_attribute(
"panel").length() == 0 )
//is not a tab element 207 return FALSE;
208
209 if( !new_tab_el.
enabled() || !new_tab_el.
visible() )
// if it is either disabled or not visible - try next 210 return select_tab( tabs_el, new_tab_el, rdirection );
211
213 }
214
216 {
217 if( he == h_tabs_container )
218 return 0;
219
222 if(panel_name.length())
223 return el; // here we are!
224
226 }
227
228
229 };
230
231 // instantiating and attaching it to the global list
233 }
Behaiviors support (a.k.a windowless scriptable controls)
bool test(const char *selector,...) const
HELEMENT prev_sibling() const
bool select_tab(dom::element &tabs_el, dom::element &tab_el, int direction)
void set_state(unsigned int bitsToSet, unsigned int bitsToClear=0, bool update=true)
void set_attribute(const char *name, const WCHAR *value)
virtual event_handler * create(HELEMENT he)
virtual void attached(HELEMENT he)
HELEMENT first_sibling() const
HELEMENT last_sibling() const
virtual bool on_mouse(HELEMENT he, HELEMENT target, UINT event_type, POINT pt, UINT mouseButtons, UINT keyboardStates)
static bool is_in_focus(const dom::element &el)
unsigned int get_state() const
bool select_tab(dom::element &tabs_el, dom::element &tab_el)
HELEMENT find_first(const char *selector,...) const
virtual bool on_event(HELEMENT he, HELEMENT target, BEHAVIOR_EVENTS type, UINT_PTR reason)
HELEMENT find_nearest_parent(const char *selector,...) const
dom::element target_tab(HELEMENT he, HELEMENT h_tabs_container)
virtual bool subscription(HELEMENT he, UINT &event_groups)
std::basic_string< WCHAR > string
sciter::string get_attribute(unsigned int n) const
HELEMENT next_sibling() const
void post_event(unsigned int event_code, unsigned int reason=0, HELEMENT heSource=0)