1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Windows
10 {
11 public class delegate void SplitterEventHandler();
12
13 public enum Orientation
14 {
15 horizontal, vertical
16 }
17
18 public nothrow Dock SplitDock(Orientation orientation)
19 {
20 switch (orientation)
21 {
22 case Orientation.horizontal: return Dock.left;
23 case Orientation.vertical: return Dock.top;
24 }
25 return Dock.none;
26 }
27
28 public nothrow Size SplitSize(Orientation orientation, int width)
29 {
30 switch (orientation)
31 {
32 case Orientation.horizontal: return Size(width, 0);
33 case Orientation.vertical: return Size(0, width);
34 }
35 return Size();
36 }
37
38 public nothrow Color DefaultSplitterEdgeColor()
39 {
40 return Color(204u, 206u, 219u);
41 }
42
43 public const int defaultSplitterWidth = 5;
44
45 public nothrow ControlCreateParams& SplitterControlCreateParams(ControlCreateParams& controlCreateParams, Orientation orientation, int width)
46 {
47 return controlCreateParams.SetWindowClassName("System.Windows.Splitter").SetSize(SplitSize(orientation, width)).SetDock(SplitDock(orientation));
48 }
49
50 public class SplitterCreateParams
51 {
52 public nothrow SplitterCreateParams(ControlCreateParams& controlCreateParams_) :
53 controlCreateParams(controlCreateParams_),
54 orientation(Orientation.horizontal),
55 edgeColor(DefaultSplitterEdgeColor())
56 {
57 }
58 public nothrow SplitterCreateParams& Defaults()
59 {
60 return *this;
61 }
62 public nothrow SplitterCreateParams& SetOrientation(Orientation orientation_)
63 {
64 orientation = orientation_;
65 return *this;
66 }
67 public nothrow SplitterCreateParams& SetEdgeColor(const Color& edgeColor_)
68 {
69 edgeColor = edgeColor_;
70 return *this;
71 }
72 public ControlCreateParams& controlCreateParams;
73 public Orientation orientation;
74 public Color edgeColor;
75 }
76
77 public class Splitter : Control
78 {
79 private enum Flags : sbyte
80 {
81 none = 0, moveSplitter = 1 << 0
82 }
83 public Splitter(Orientation orientation_, const Color& backgroundColor, const Color& edgeColor_, const Point& location, int width) :
84 base("System.Windows.Splitter", DefaultWindowClassStyle(), DefaultChildWindowStyle(), DefaultExtendedWindowStyle(),
85 backgroundColor, "splitter", location, SplitSize(orientation_, width), SplitDock(orientation_), Anchors.none),
86 orientation(orientation_),
87 horizontalSplitterCursor(Application.GetResourceManager().GetCursor("horizontal.splitter.system.windows.cursor")),
88 verticalSplitterCursor(Application.GetResourceManager().GetCursor("vertical.splitter.system.windows.cursor")), flags(), container(null),
89 edgeColor(edgeColor_), edgePen(edgeColor)
90 {
91 }
92 public Splitter(Orientation orientation, const Point& location) :
93 this(orientation, DefaultControlBackgroundColor(), DefaultSplitterEdgeColor(), location, defaultSplitterWidth)
94 {
95 }
96 public Splitter(SplitterCreateParams& createParams) :
97 base(createParams.controlCreateParams),
98 orientation(createParams.orientation),
99 horizontalSplitterCursor(Application.GetResourceManager().GetCursor("horizontal.splitter.system.windows.cursor")),
100 verticalSplitterCursor(Application.GetResourceManager().GetCursor("vertical.splitter.system.windows.cursor")), flags(), container(null),
101 edgeColor(createParams.edgeColor), edgePen(edgeColor)
102 {
103 }
104 public nothrow void SetContainer(SplitContainer* container_)
105 {
106 container = container_;
107 }
108 public override void PrintWindowTree(int level)
109 {
110 LogView* log = Application.GetLogView();
111 if (log != null)
112 {
113 log->WriteLine(string(' ', level) + "Splitter." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Point(), GetSize()).ToString() + "]");
114 }
115 }
116 protected override void OnPaint(PaintEventArgs& args)
117 {
118 try
119 {
120 if (Debug.Paint())
121 {
122 Rect r(Point(), GetSize());
123 LogView* log = Application.GetLogView();
124 if (log != null)
125 {
126 log->WriteLine("Splitter.OnPaint: " + r.ToString());
127 }
128 }
129 args.graphics.Clear(BackgroundColor());
130 Size size = GetSize();
131 LogView* log = Application.GetLogView();
132 switch (orientation)
133 {
134 case Orientation.horizontal:
135 {
136 args.graphics.DrawLineChecked(edgePen, Point(0, 0), Point(0, size.h - 1));
137 args.graphics.DrawLineChecked(edgePen, Point(size.w - 1, 0), Point(size.w - 1, size.h - 1));
138 break;
139 }
140 case Orientation.vertical:
141 {
142 args.graphics.DrawLineChecked(edgePen, Point(0, 0), Point(size.w - 1, 0));
143 args.graphics.DrawLineChecked(edgePen, Point(0, size.h - 1), Point(size.w - 1, size.h - 1));
144 break;
145 }
146 }
147 base->OnPaint(args);
148 }
149 catch (const Exception& ex)
150 {
151 MessageBox.Show(ex.Message());
152 }
153 }
154 protected override void SetCursor()
155 {
156 switch (orientation)
157 {
158 case Orientation.horizontal: SetCursor(horizontalSplitterCursor); break;
159 case Orientation.vertical: SetCursor(verticalSplitterCursor); break;
160 }
161 }
162 protected override void OnMouseDown(MouseEventArgs& args)
163 {
164 try
165 {
166 base->OnMouseDown(args);
167 if (args.buttons == MouseButtons.lbutton)
168 {
169 SetFlag(Flags.moveSplitter);
170 switch (orientation)
171 {
172 case Orientation.horizontal:
173 {
174 x = args.location.x;
175 break;
176 }
177 case Orientation.vertical:
178 {
179 y = args.location.y;
180 break;
181 }
182 }
183 WinSetCapture(Handle());
184 }
185 }
186 catch (const Exception& ex)
187 {
188 MessageBox.Show(ex.Message());
189 }
190 }
191 protected override void OnMouseMove(MouseEventArgs& args)
192 {
193 try
194 {
195 if (GetFlag(Flags.moveSplitter))
196 {
197 switch (orientation)
198 {
199 case Orientation.horizontal:
200 {
201 int dx = args.location.x - x;
202 container->SetSplitterDistance(container->SplitterDistance() + dx);
203 break;
204 }
205 case Orientation.vertical:
206 {
207 int dy = args.location.y - y;
208 container->SetSplitterDistance(container->SplitterDistance() + dy);
209 break;
210 }
211 }
212 }
213 }
214 catch (const Exception& ex)
215 {
216 MessageBox.Show(ex.Message());
217 }
218 }
219 protected override void OnMouseUp(MouseEventArgs& args)
220 {
221 try
222 {
223 base->OnMouseUp(args);
224 if (GetFlag(Flags.moveSplitter))
225 {
226 ResetFlag(Flags.moveSplitter);
227 WinReleaseCapture();
228 switch (orientation)
229 {
230 case Orientation.horizontal:
231 {
232 int dx = args.location.x - x;
233 container->SetSplitterDistance(container->SplitterDistance() + dx);
234 break;
235 }
236 case Orientation.vertical:
237 {
238 int dy = args.location.y - y;
239 container->SetSplitterDistance(container->SplitterDistance() + dy);
240 break;
241 }
242 }
243 }
244 }
245 catch (const Exception& ex)
246 {
247 MessageBox.Show(ex.Message());
248 }
249 }
250 private inline nothrow void SetFlag(Flags flag)
251 {
252 flags = cast<Flags>(flags | flag);
253 }
254 private inline nothrow void ResetFlag(Flags flag)
255 {
256 flags = cast<Flags>(flags & ~flag);
257 }
258 private inline nothrow bool GetFlag(Flags flag) const
259 {
260 return (flags & flag) != 0;
261 }
262 private Orientation orientation;
263 private Cursor& horizontalSplitterCursor;
264 private Cursor& verticalSplitterCursor;
265 private Flags flags;
266 private int x;
267 private int y;
268 private SplitContainer* container;
269 private Color edgeColor;
270 private Pen edgePen;
271 }
272
273 public nothrow ControlCreateParams& SplitContainerControlCreateParams(ControlCreateParams& controlCreateParams)
274 {
275 return controlCreateParams.SetWindowClassName("System.Windows.SplitContainer");
276 }
277
278 public class SplitContainerCreateParams
279 {
280 public nothrow SplitContainerCreateParams(ControlCreateParams& controlCreateParams_,
281 Orientation orientation_, Control* pane1_, Splitter* splitter_, Control* pane2_, int splitterDistance_) :
282 controlCreateParams(controlCreateParams_), orientation(orientation_), pane1(pane1_), splitter(splitter_), pane2(pane2_),
283 splitterWidth(defaultSplitterWidth), splitterDistance(splitterDistance_)
284 {
285 }
286 public nothrow SplitContainerCreateParams& Defaults()
287 {
288 return *this;
289 }
290 public nothrow SplitContainerCreateParams& SetSplitterWidth(int splitterWidth_)
291 {
292 splitterWidth = splitterWidth_;
293 return *this;
294 }
295 public nothrow SplitContainerCreateParams& SetSplitterDistance(int splitterDistance_)
296 {
297 splitterDistance = splitterDistance_;
298 return *this;
299 }
300 public ControlCreateParams& controlCreateParams;
301 public Orientation orientation;
302 public Control* pane1;
303 public Splitter* splitter;
304 public Control* pane2;
305 public int splitterWidth;
306 public int splitterDistance;
307 }
308
309 public class SplitContainer : ContainerControl
310 {
311 public SplitContainer(Orientation orientation_, Control* pane1_, Splitter* splitter_, Control* pane2_, int splitterWidth, int splitterDistance_,
312 const Point& location, const Size& size, Dock dock, Anchors anchors) :
313 base("System.Windows.SplitContainer", DefaultWindowClassStyle(), DefaultChildWindowStyle(), DefaultExtendedWindowStyle(),
314 DefaultControlBackgroundColor(), "splitContainer", location, size, dock, anchors),
315 orientation(orientation_), pane1(pane1_), splitter(splitter_), pane2(pane2_), splitterDistance(splitterDistance_)
316 {
317 Init();
318 }
319 public SplitContainer(Orientation orientation, int splitterDistance, const Point& location, const Size& size, Dock dock, Anchors anchors) :
320 this(orientation,
321 new Panel(location, SplitSize(orientation, splitterDistance), SplitDock(orientation), Anchors.none),
322 new Splitter(orientation, location),
323 new Panel(location, SplitSize(orientation, splitterDistance), SplitDock(orientation), Anchors.none),
324 defaultSplitterWidth, splitterDistance, location, size, dock, anchors)
325 {
326 }
327 public SplitContainer(SplitContainerCreateParams& createParams) :
328 base(createParams.controlCreateParams),
329 orientation(createParams.orientation),
330 pane1(createParams.pane1), splitter(createParams.splitter), pane2(createParams.pane2), splitterDistance(createParams.splitterDistance)
331 {
332 Init();
333 }
334 private void Init()
335 {
336 pane1->SetSize(SplitSize(orientation, splitterDistance));
337 pane1->SetDock(SplitDock(orientation));
338 AddChild(pane1);
339 splitter->SetContainer(this);
340 AddChild(splitter);
341 pane2->SetLocation(Location());
342 pane2->SetDock(Dock.fill);
343 AddChild(pane2);
344 }
345 public override void OnPaint(PaintEventArgs& args)
346 {
347 Size size = GetSize();
348 if (splitterDistance == 0)
349 {
350 int s = 0;
351 switch (orientation)
352 {
353 case Orientation.horizontal: s = size.w; break;
354 case Orientation.vertical: s = size.h; break;
355 }
356 int d = cast<int>((2.0 / 3.0) * s);
357 SetSplitterDistance(d);
358 }
359 base->OnPaint(args);
360 }
361 public override void PrintWindowTree(int level)
362 {
363 LogView* log = Application.GetLogView();
364 if (log != null)
365 {
366 log->WriteLine(string(' ', level) + "SplitContainer." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Point(), GetSize()).ToString() + "]");
367 }
368 Component* child = Children().FirstChild();
369 while (child != null)
370 {
371 if (child is Control*)
372 {
373 Control* childControl = cast<Control*>(child);
374 childControl->PrintWindowTree(level + 1);
375 }
376 child = child->NextSibling();
377 }
378 }
379 public inline nothrow Orientation GetOrientation() const
380 {
381 return orientation;
382 }
383 public inline nothrow ContainerControl* Pane1Container() const
384 {
385 return pane1->GetContainerControl();
386 }
387 public inline nothrow Splitter* GetSplitter() const
388 {
389 return splitter;
390 }
391 public inline nothrow ContainerControl* Pane2Container() const
392 {
393 return pane2->GetContainerControl();
394 }
395 public inline nothrow int SplitterDistance() const
396 {
397 return splitterDistance;
398 }
399 public void SetSplitterDistance(int splitterDistance_)
400 {
401 int prevSplitterDistance = splitterDistance;
402 splitterDistance = splitterDistance_;
403 switch (orientation)
404 {
405 case Orientation.horizontal: pane1->SetSize(Size(splitterDistance, pane1->GetSize().h)); break;
406 case Orientation.vertical: pane1->SetSize(Size(pane1->GetSize().w, splitterDistance)); break;
407 }
408 DockChildren();
409 Invalidate();
410 if (prevSplitterDistance != splitterDistance)
411 {
412 OnSplitterDistanceChanged();
413 }
414 }
415 public virtual void OnSplitterDistanceChanged()
416 {
417 splitterDistanceChangedEvent.Fire();
418 }
419 public nothrow Control* Pane1() const
420 {
421 return pane1;
422 }
423 public nothrow Control* Pane2() const
424 {
425 return pane2;
426 }
427 public nothrow Event<SplitterEventHandler>& SplitterDistanceChangedEvent() const
428 {
429 return splitterDistanceChangedEvent;
430 }
431 private Orientation orientation;
432 private int splitterDistance;
433 private Control* pane1;
434 private Splitter* splitter;
435 private Control* pane2;
436 private Event<SplitterEventHandler> splitterDistanceChangedEvent;
437 }
438 }