source: Docking/CoolDocking/UCDLayout.pas

Last change on this file was 437, checked in by chronos, 12 years ago
  • Fixed: Better switching tabbed controls.
File size: 17.7 KB
Line 
1unit UCDLayout;
2
3{$mode Delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, FileUtil, Contnrs, SpecializedRectangle, Forms, UCDCommon,
9 DOM, XMLWrite, XMLRead, Controls, Dialogs;
10
11type
12 TCDLayout = class;
13
14 { TCDLayoutItem }
15
16 TCDLayoutItem = class
17 Parent: TCDLayout;
18 Name: string;
19 StoredClassName: string;
20 ParentName: string;
21 HostDockSiteName: string;
22 Caption: string;
23 Visible: boolean;
24 Rect: TRectangle;
25 RestoredRect: TRectangle;
26 WindowState: TWindowState;
27 UndockSize: TPoint;
28 DockStyle: TCDStyleType;
29 HeaderPos: THeaderPos;
30 Processed: boolean;
31 procedure SaveToNode(Node: TDOMNode);
32 procedure LoadFromNode(Node: TDOMNode);
33 procedure Store(Form: TWinControl);
34 procedure Restore(Form: TWinControl);
35 constructor Create;
36 destructor Destroy; override;
37 end;
38
39 { TCDLayout }
40
41 TCDLayout = class
42 Items: TObjectList; // TList<TCDLayoutItem>
43 Name: string;
44 procedure SaveToNode(Node: TDOMNode);
45 procedure LoadFromNode(Node: TDOMNode);
46 function FindByName(Name: string): TCDLayoutItem;
47 constructor Create;
48 destructor Destroy; override;
49 procedure Store;
50 procedure Restore;
51 end;
52
53 { TCDLayoutList }
54
55 TCDLayoutList = class(TComponent)
56 public
57 Items: TObjectList; // TList<TCDLayout>
58 procedure LoadFromStream(Stream: TStream);
59 procedure SaveToStream(Stream: TStream);
60 procedure LoadFromFile(FileName: string);
61 procedure SaveToFile(FileName: string);
62 procedure LoadFromString(Value: string);
63 function SaveToString: string;
64 procedure PopulateStringList(List: TStrings);
65 function FindByName(Name: string): TCDLayout;
66 constructor Create(AOwner: TComponent); override;
67 destructor Destroy; override;
68 end;
69
70procedure Register;
71
72implementation
73
74uses
75 UCDManager, UCDConjoinForm;
76
77procedure Register;
78begin
79 RegisterComponents('CoolDocking', [TCDLayoutList]);
80end;
81
82function FindGlobalComponentDeep(Name: string): TComponent;
83var
84 I: integer;
85begin
86 for I := 0 to Application.ComponentCount - 1 do
87 begin
88 Result := Application.Components[I];
89 if Result.Name = Name then
90 Exit
91 else
92 begin
93 Result := Result.FindComponent(Name);
94 if Assigned(Result) and (Result.Name = Name) then
95 Exit;
96 end;
97 end;
98end;
99
100{ TCDLayoutList }
101
102
103constructor TCDLayoutList.Create(AOwner: TComponent);
104begin
105 inherited;
106 Items := TObjectList.Create;
107end;
108
109destructor TCDLayoutList.Destroy;
110begin
111 Items.Free;
112 inherited Destroy;
113end;
114
115procedure TCDLayoutList.LoadFromStream(Stream: TStream);
116var
117 Doc: TXMLDocument;
118 Child: TDOMNode;
119 NewItem: TCDLayout;
120 NewNode: TDOMNode;
121begin
122 try
123 ReadXMLFile(Doc, Stream);
124 Items.Clear;
125 with Doc.DocumentElement do
126 begin
127 NewNode := FindNode('Items');
128 if Assigned(NewNode) then
129 with NewNode do
130 begin
131 Child := FirstChild;
132 while Assigned(Child) do
133 begin
134 NewItem := TCDLayout.Create;
135 NewItem.LoadFromNode(Child);
136 Items.Add(NewItem);
137 Child := Child.NextSibling;
138 end;
139 end;
140 end;
141 finally
142 Doc.Free;
143 end;
144end;
145
146procedure TCDLayoutList.SaveToStream(Stream: TStream);
147var
148 Doc: TXMLDocument;
149 RootNode: TDOMNode;
150 I: integer;
151 NewNode: TDOMNode;
152 NewNode2: TDOMNode;
153begin
154 try
155 Doc := TXMLDocument.Create;
156 with Doc do
157 begin
158 RootNode := CreateElement('CoolDockLayout');
159 AppendChild(RootNode);
160 with RootNode do
161 begin
162 NewNode := OwnerDocument.CreateElement('Items');
163 with NewNode do
164 for I := 0 to Items.Count - 1 do
165 begin
166 NewNode2 := OwnerDocument.CreateElement('Layout');
167 TCDLayout(Items[I]).SaveToNode(NewNode2);
168 AppendChild(NewNode2);
169 end;
170 AppendChild(NewNode);
171 end;
172 end;
173 WriteXMLFile(Doc, Stream);
174 finally
175 Doc.Free;
176 end;
177end;
178
179procedure TCDLayoutList.LoadFromFile(FileName: string);
180var
181 Stream: TFileStream;
182begin
183 try
184 Stream := TFileStream.Create(FileName, fmOpenRead);
185 LoadFromStream(Stream);
186 finally
187 Stream.Free;
188 end;
189end;
190
191procedure TCDLayoutList.SaveToFile(FileName: string);
192var
193 Stream: TFileStream;
194begin
195 try
196 if FileExistsUTF8(FileName) then
197 Stream := TFileStream.Create(FileName, fmOpenReadWrite)
198 else
199 Stream := TFileStream.Create(FileName, fmCreate);
200 Stream.Size := 0;
201 SaveToStream(Stream);
202 finally
203 Stream.Free;
204 end;
205end;
206
207procedure TCDLayoutList.LoadFromString(Value: string);
208var
209 Stream: TMemoryStream;
210begin
211 if Length(Value) > 0 then
212 try
213 Stream := TMemoryStream.Create;
214 Stream.WriteBuffer(Value[1], Length(Value));
215 Stream.Position := 0;
216 LoadFromStream(Stream);
217 finally
218 Stream.Free;
219 end;
220end;
221
222function TCDLayoutList.SaveToString: string;
223var
224 Stream: TMemoryStream;
225begin
226 Result := '';
227 try
228 Stream := TMemoryStream.Create;
229 Stream.Size := 0;
230 SaveToStream(Stream);
231 if Stream.Size > 0 then begin
232 SetLength(Result, Stream.Size);
233 Stream.Position := 0;
234 Stream.ReadBuffer(Result[1], Stream.Size);
235 end;
236 finally
237 Stream.Free;
238 end;
239end;
240
241procedure TCDLayoutList.PopulateStringList(List: TStrings);
242var
243 I: integer;
244begin
245 List.Clear;
246 for I := 0 to Items.Count - 1 do
247 List.AddObject(TCDLayout(Items[I]).Name, TCDLayout(Items[I]));
248end;
249
250function TCDLayoutList.FindByName(Name: string): TCDLayout;
251var
252 I: integer;
253begin
254 I := 0;
255 while (I < Items.Count) and (TCDLayout(Items[I]).Name <> Name) do
256 Inc(I);
257 if I < Items.Count then
258 Result := TCDLayout(Items[I])
259 else
260 Result := nil;
261end;
262
263{ TCDLayoutItem }
264
265procedure TCDLayoutItem.SaveToNode(Node: TDOMNode);
266var
267 NewNode: TDOMNode;
268begin
269 with Node do
270 begin
271 NewNode := OwnerDocument.CreateElement('Name');
272 NewNode.TextContent := UTF8Decode(Name);
273 AppendChild(NewNode);
274 NewNode := OwnerDocument.CreateElement('ParentName');
275 NewNode.TextContent := UTF8Decode(ParentName);
276 AppendChild(NewNode);
277 NewNode := OwnerDocument.CreateElement('StoredClassName');
278 NewNode.TextContent := UTF8Decode(StoredClassName);
279 AppendChild(NewNode);
280 NewNode := OwnerDocument.CreateElement('HostDockSiteName');
281 NewNode.TextContent := UTF8Decode(HostDockSiteName);
282 AppendChild(NewNode);
283 NewNode := OwnerDocument.CreateElement('Caption');
284 NewNode.TextContent := UTF8Decode(Caption);
285 AppendChild(NewNode);
286 NewNode := OwnerDocument.CreateElement('WindowState');
287 NewNode.TextContent := IntToStr(integer(WindowState));
288 AppendChild(NewNode);
289 NewNode := OwnerDocument.CreateElement('UndockWidth');
290 NewNode.TextContent := IntToStr(UndockSize.X);
291 AppendChild(NewNode);
292 NewNode := OwnerDocument.CreateElement('UndockHeight');
293 NewNode.TextContent := IntToStr(UndockSize.Y);
294 AppendChild(NewNode);
295 NewNode := OwnerDocument.CreateElement('Width');
296 NewNode.TextContent := IntToStr(Rect.Width);
297 AppendChild(NewNode);
298 NewNode := OwnerDocument.CreateElement('Height');
299 NewNode.TextContent := IntToStr(Rect.Height);
300 AppendChild(NewNode);
301 NewNode := OwnerDocument.CreateElement('Top');
302 NewNode.TextContent := IntToStr(Rect.Top);
303 AppendChild(NewNode);
304 NewNode := OwnerDocument.CreateElement('Left');
305 NewNode.TextContent := IntToStr(Rect.Left);
306 AppendChild(NewNode);
307 NewNode := OwnerDocument.CreateElement('Visible');
308 NewNode.TextContent := BoolToStr(Visible);
309 AppendChild(NewNode);
310 NewNode := OwnerDocument.CreateElement('DockStyle');
311 NewNode.TextContent := IntToStr(integer(DockStyle));
312 AppendChild(NewNode);
313 NewNode := OwnerDocument.CreateElement('RestoredWidth');
314 NewNode.TextContent := IntToStr(RestoredRect.Width);
315 AppendChild(NewNode);
316 NewNode := OwnerDocument.CreateElement('RestoredHeight');
317 NewNode.TextContent := IntToStr(RestoredRect.Height);
318 AppendChild(NewNode);
319 NewNode := OwnerDocument.CreateElement('RestoredTop');
320 NewNode.TextContent := IntToStr(RestoredRect.Top);
321 AppendChild(NewNode);
322 NewNode := OwnerDocument.CreateElement('RestoredLeft');
323 NewNode.TextContent := IntToStr(RestoredRect.Left);
324 AppendChild(NewNode);
325 NewNode := OwnerDocument.CreateElement('HeaderPos');
326 NewNode.TextContent := IntToStr(Integer(HeaderPos));
327 AppendChild(NewNode);
328 end;
329end;
330
331procedure TCDLayoutItem.LoadFromNode(Node: TDOMNode);
332var
333 NewNode: TDOMNode;
334begin
335 with TDOMElement(Node) do
336 begin
337 NewNode := FindNode('Name');
338 if Assigned(NewNode) then
339 Name := UTF8Encode(NewNode.TextContent);
340 NewNode := FindNode('ParentName');
341 if Assigned(NewNode) then
342 ParentName := UTF8Encode(NewNode.TextContent);
343 NewNode := FindNode('StoredClassName');
344 if Assigned(NewNode) then
345 StoredClassName := UTF8Encode(NewNode.TextContent);
346 NewNode := FindNode('HostDockSiteName');
347 if Assigned(NewNode) then
348 HostDockSiteName := UTF8Encode(NewNode.TextContent);
349 NewNode := FindNode('Caption');
350 if Assigned(NewNode) then
351 Caption := UTF8Encode(NewNode.TextContent);
352 NewNode := FindNode('WindowState');
353 if Assigned(NewNode) then
354 WindowState := TWindowState(StrToInt(NewNode.TextContent));
355 NewNode := FindNode('UndockWidth');
356 if Assigned(NewNode) then
357 UndockSize.X := StrToInt(NewNode.TextContent);
358 NewNode := FindNode('UndockHeight');
359 if Assigned(NewNode) then
360 UndockSize.Y := StrToInt(NewNode.TextContent);
361 NewNode := FindNode('Top');
362 if Assigned(NewNode) then
363 Rect.Top := StrToInt(NewNode.TextContent);
364 NewNode := FindNode('Left');
365 if Assigned(NewNode) then
366 Rect.Left := StrToInt(NewNode.TextContent);
367 NewNode := FindNode('Width');
368 if Assigned(NewNode) then
369 Rect.Width := StrToInt(NewNode.TextContent);
370 NewNode := FindNode('Height');
371 if Assigned(NewNode) then
372 Rect.Height := StrToInt(NewNode.TextContent);
373 NewNode := FindNode('Visible');
374 if Assigned(NewNode) then
375 Visible := StrToBool(NewNode.TextContent);
376 NewNode := FindNode('DockStyle');
377 if Assigned(NewNode) then
378 DockStyle := TCDStyleType(StrToInt(NewNode.TextContent));
379 NewNode := FindNode('RestoredTop');
380 if Assigned(NewNode) then
381 RestoredRect.Top := StrToInt(NewNode.TextContent);
382 NewNode := FindNode('RestoredLeft');
383 if Assigned(NewNode) then
384 RestoredRect.Left := StrToInt(NewNode.TextContent);
385 NewNode := FindNode('RestoredWidth');
386 if Assigned(NewNode) then
387 RestoredRect.Width := StrToInt(NewNode.TextContent);
388 NewNode := FindNode('RestoredHeight');
389 if Assigned(NewNode) then
390 RestoredRect.Height := StrToInt(NewNode.TextContent);
391 NewNode := FindNode('HeaderPos');
392 if Assigned(NewNode) then
393 HeaderPos := THeaderPos(StrToInt(NewNode.TextContent));
394 end;
395end;
396
397procedure TCDLayoutItem.Store(Form: TWinControl);
398var
399 NewItem: TCDLayoutItem;
400begin
401 Name := Form.Name;
402 StoredClassName := Form.ClassName;
403 Caption := Form.Caption;
404 UndockSize.X := Form.UndockWidth;
405 UndockSize.Y := Form.UndockHeight;
406 Visible := Form.Visible or (TCDHideType(Form.Tag) = dhtTemporal);
407 Rect.Left := Form.Left;
408 Rect.Top := Form.Top;
409 Rect.Width := Form.Width;
410 Rect.Height := Form.Height;
411 if Assigned(Form.DockManager) then
412 HeaderPos := TCDManager(Form.DockManager).HeaderPos;
413 if Form is TForm then
414 begin
415 RestoredRect.Left := TForm(Form).RestoredLeft;
416 RestoredRect.Top := TForm(Form).RestoredTop;
417 RestoredRect.Width := TForm(Form).RestoredWidth;
418 RestoredRect.Height := TForm(Form).RestoredHeight;
419 WindowState := TForm(Form).WindowState;
420 end;
421 if Assigned(Form.Parent) then
422 ParentName := Form.Parent.Name
423 else
424 ParentName := '';
425 if Assigned(Form.HostDockSite) then
426 begin
427 if Assigned(Form.HostDockSite) then
428 begin
429 HostDockSiteName := Form.HostDockSite.Name;
430 if not Assigned(Parent.FindByName(HostDockSiteName)) then
431 begin
432 NewItem := TCDLayoutItem.Create;
433 NewItem.Parent := Parent;
434 NewItem.DockStyle := TCDManager(Form.HostDockSite.DockManager).DockStyle;
435 Parent.Items.Add(NewItem);
436 NewItem.Store(Form.HostDockSite);
437 end;
438 end;
439 end
440 else
441 HostDockSiteName := '';
442end;
443
444procedure TCDLayoutItem.Restore(Form: TWinControl);
445var
446 ParentComponent: TComponent;
447 ParentLayoutItem: TCDLayoutItem;
448 FormClass: TFormClass;
449begin
450 if Form is TForm then
451 if WindowState = wsMaximized then
452 begin
453 TForm(Form).SetRestoredBounds(RestoredRect.Left, RestoredRect.Top,
454 RestoredRect.Width, RestoredRect.Height);
455 TForm(Form).WindowState := WindowState;
456 end
457 else
458 begin
459 TForm(Form).WindowState := WindowState;
460 TForm(Form).SetRestoredBounds(RestoredRect.Left, RestoredRect.Top,
461 RestoredRect.Width, RestoredRect.Height);
462 end;
463 Form.Name := Name;
464 Form.Caption := Caption;
465 Form.SetBounds(Rect.Left, Rect.Top, Rect.Width, Rect.Height);
466 Form.UndockWidth := UndockSize.X;
467 Form.UndockHeight := UndockSize.Y;
468 Form.Visible := Visible;
469 if Assigned(Form.DockManager) then
470 TCDManager(Form.DockManager).HeaderPos := HeaderPos;
471 if HostDockSiteName <> '' then
472 begin
473 ParentComponent := FindGlobalComponentDeep(HostDockSiteName);
474 if not Assigned(ParentComponent) then
475 begin
476 ParentLayoutItem := Parent.FindByName(HostDockSiteName);
477 if Assigned(ParentLayoutItem) then
478 begin
479 if ParentLayoutItem.StoredClassName <> '' then
480 begin
481 //ParentComponent := TComponent(FindClass(ParentLayoutItem.StoredClassName).Create);
482 if (ParentLayoutItem.StoredClassName = 'TCDConjoinForm') then
483 begin
484 FormClass := TFormClass(FindClass('TCDConjoinForm'));
485 if FormClass = TCDConjoinForm then
486 begin
487 ParentComponent := TCDManager(Form.DockManager).CreateConjoinForm;
488 TCDManager(TCDConjoinForm(ParentComponent).DockManager).DockStyle :=
489 ParentLayoutItem.DockStyle;
490 ParentLayoutItem.Restore(TWinControl(ParentComponent));
491 end;
492 end;
493 end;
494 end;
495 end;
496 if Assigned(ParentComponent) and (ParentComponent is TWinControl) then
497 Form.ManualDock(TWinControl(ParentComponent));
498 end;
499 Processed := True;
500end;
501
502constructor TCDLayoutItem.Create;
503begin
504 Rect := TRectangle.Create;
505 RestoredRect := TRectangle.Create;
506end;
507
508destructor TCDLayoutItem.Destroy;
509begin
510 Rect.Free;
511 RestoredRect.Free;
512 inherited Destroy;
513end;
514
515{ TCDLayout }
516
517procedure TCDLayout.SaveToNode(Node: TDOMNode);
518var
519 NewNode: TDOMNode;
520 NewNode2: TDOMNode;
521 I: integer;
522begin
523 with Node do
524 begin
525 NewNode := OwnerDocument.CreateElement('Name');
526 NewNode.TextContent := UTF8Decode(Name);
527 AppendChild(NewNode);
528 NewNode := OwnerDocument.CreateElement('Items');
529 with NewNode do
530 for I := 0 to Items.Count - 1 do
531 begin
532 NewNode2 := OwnerDocument.CreateElement('Form');
533 TCDLayoutItem(Items[I]).SaveToNode(NewNode2);
534 AppendChild(NewNode2);
535 end;
536 AppendChild(NewNode);
537 end;
538end;
539
540procedure TCDLayout.LoadFromNode(Node: TDOMNode);
541var
542 NewNode: TDOMNode;
543 Child: TDOMNode;
544 NewItem: TCDLayoutItem;
545begin
546 with Node do
547 begin
548 NewNode := FindNode('Name');
549 if Assigned(NewNode) then
550 Name := UTF8Encode(NewNode.TextContent);
551 NewNode := FindNode('Items');
552 if Assigned(NewNode) then
553 with NewNode do
554 begin
555 Child := FirstChild;
556 while Assigned(Child) do
557 begin
558 NewItem := TCDLayoutItem.Create;
559 NewItem.Parent := Self;
560 NewItem.LoadFromNode(Child);
561 Items.Add(NewItem);
562 Child := Child.NextSibling;
563 end;
564 end;
565 end;
566end;
567
568function TCDLayout.FindByName(Name: string): TCDLayoutItem;
569var
570 I: integer;
571begin
572 I := 0;
573 while (I < Items.Count) and (TCDLayoutItem(Items[I]).Name <> Name) do
574 Inc(I);
575 if I < Items.Count then
576 Result := TCDLayoutItem(Items[I])
577 else
578 Result := nil;
579end;
580
581constructor TCDLayout.Create;
582begin
583 Items := TObjectList.Create;
584end;
585
586destructor TCDLayout.Destroy;
587begin
588 Items.Free;
589 inherited Destroy;
590end;
591
592procedure TCDLayout.Store;
593var
594 I: integer;
595 Form: TForm;
596 NewItem: TCDLayoutItem;
597begin
598 Items.Clear;
599 for I := 0 to Application.ComponentCount - 1 do
600 if (Application.Components[I] is TForm) then
601 begin
602 Form := (Application.Components[I] as TForm);
603 NewItem := TCDLayoutItem.Create;
604 NewItem.Parent := Self;
605 NewItem.Store(Form);
606 Items.Add(NewItem);
607 end;
608end;
609
610procedure TCDLayout.Restore;
611var
612 Form: TForm;
613 I: integer;
614begin
615 // Undock all forms
616 I := 0;
617 while (I < Application.ComponentCount) do
618 begin
619 if (Application.Components[I] is TForm) then
620 begin
621 Form := (Application.Components[I] as TForm);
622 if Assigned(Form.HostDockSite) then
623 Form.ManualFloat(Rect(Form.Left, Form.Top, Form.Left +
624 Form.Width, Form.Top + Form.Height));
625 end;
626 Inc(I);
627 end;
628
629 for I := 0 to Items.Count - 1 do
630 with TCDLayoutItem(Items[I]) do
631 Processed := False;
632
633 for I := 0 to Items.Count - 1 do
634 with TCDLayoutItem(Items[I]) do
635 begin
636 Form := TForm(Application.FindComponent(Name));
637 if Assigned(Form) and (not Assigned(Form.HostDockSite)) and (not Processed) then
638 Restore(Form);
639 end;
640end;
641
642end.
643
Note: See TracBrowser for help on using the repository browser.