source: branches/overos/Os.Window.pas

Last change on this file was 39, checked in by chronos, 11 months ago
  • Modified: Simplified unit names.
File size: 12.8 KB
Line 
1unit Os.Window;
2
3interface
4
5uses
6 Classes, SysUtils, Generics.Collections, Os.Types, Os.Mouse, Os.Controls, Os.Graphics;
7
8type
9 TScreen = class;
10 TWindow = class;
11
12 { TCanvasWindow }
13
14 TCanvasWindow = class(TCanvas)
15 Window: TWindow;
16 procedure DrawLine(P1, P2: TPosition; Color: TColor); override;
17 procedure DrawArea(Rect: TRectangle; Color: TColor); override;
18 procedure DrawText(P: TPosition; Color: TColor; Text: string); override;
19 function GetTextSize(Text: string): TSize; override;
20 end;
21
22 TWindowSide = (wsNone, wsLeft, wsTop, wsRight, wsBottom);
23
24 { TTitleBar }
25
26 TTitleBar = class(TControl)
27 private
28 FWindow: TWindow;
29 procedure SetWindow(AValue: TWindow);
30 procedure ButtonCloseClick(Sender: TObject);
31 procedure ButtonMaximizeClick(Sender: TObject);
32 procedure ButtonMinimizeClick(Sender: TObject);
33 protected
34 procedure SetRectangle(AValue: TRectangle); override;
35 public
36 const
37 TitleHeight = 32;
38 var
39 ButtonClose: TButton;
40 ButtonMaximize: TButton;
41 ButtonMinimize: TButton;
42 constructor Create; override;
43 destructor Destroy; override;
44 property Window: TWindow read FWindow write SetWindow;
45 end;
46
47 TMessageWindow = class(TMessage);
48 TMessageWindowClose = class(TMessageWindow);
49 TMessageWindowMaximize = class(TMessageWindow);
50
51 { TWindow }
52
53 TWindow = class(TControl)
54 private
55 FScreen: TScreen;
56 procedure SetScreen(AValue: TScreen);
57 protected
58 procedure SetRectangle(AValue: TRectangle); override;
59 procedure SetVisible(AValue: Boolean); override;
60 public
61 const
62 BorderGrabWidth = 15;
63 var
64 TitleBar: TTitleBar;
65 Title: string;
66 Application: TObject; // TApplication
67 procedure HandleMessage(Message: TMessage);
68 procedure MouseButtonDown(Pos: TPosition; Button: TMouseButton); override;
69 procedure MouseButtonUp(Pos: TPosition; Button: TMouseButton); override;
70 procedure Close;
71 procedure Maximize;
72 procedure Focus;
73 procedure Paint; override;
74 function Focused: Boolean;
75 constructor Create; override;
76 destructor Destroy; override;
77 property Screen: TScreen read FScreen write SetScreen;
78 end;
79
80 { TScreen }
81
82 TScreen = class
83 private
84 FMouse: TMouse;
85 GrabActive: Boolean;
86 GrabWindow: TWindow;
87 GrabMousePosition: TPosition;
88 GrabWindowRectangle: TRectangle;
89 GrabWindowSide: TWindowSide;
90 procedure MouseButtonDown(Pos: TPosition; Button: TMouseButton);
91 procedure MouseButtonUp(Pos: TPosition; Button: TMouseButton);
92 procedure MouseMove(Pos: TPosition);
93 procedure SetMouse(AValue: TMouse);
94 public
95 Canvas: TCanvas;
96 Windows: TObjectList<TWindow>;
97 Size: TSize;
98 procedure Paint;
99 function CreateWindow(Title: string): TWindow;
100 constructor Create;
101 destructor Destroy; override;
102 property Mouse: TMouse read FMouse write SetMouse;
103 end;
104
105
106implementation
107
108uses
109 Os.Application;
110
111{ TTitleBar }
112
113procedure TTitleBar.SetWindow(AValue: TWindow);
114begin
115 if FWindow = AValue then Exit;
116 FreeAndNil(Canvas);
117 FWindow := AValue;
118 Canvas := TCanvasWindow.Create;
119 TCanvasWindow(Canvas).Window := FWindow;
120end;
121
122procedure TTitleBar.ButtonCloseClick(Sender: TObject);
123begin
124 Window.Close;
125end;
126
127procedure TTitleBar.ButtonMaximizeClick(Sender: TObject);
128begin
129 Window.Maximize;
130end;
131
132procedure TTitleBar.ButtonMinimizeClick(Sender: TObject);
133begin
134
135end;
136
137procedure TTitleBar.SetRectangle(AValue: TRectangle);
138begin
139 inherited;
140 ButtonClose.Rectangle := TRectangle.Create(TPosition.Create(Size.Width - TitleHeight, 4),
141 TSize.Create(TitleHeight - 8, TitleHeight - 8));
142 ButtonMaximize.Rectangle := TRectangle.Create(TPosition.Create(Size.Width - 2 * TitleHeight, 4),
143 TSize.Create(TitleHeight - 8, TitleHeight - 8));
144 ButtonMinimize.Rectangle := TRectangle.Create(TPosition.Create(Size.Width - 3 * TitleHeight, 4),
145 TSize.Create(TitleHeight - 8, TitleHeight - 8));
146end;
147
148constructor TTitleBar.Create;
149begin
150 inherited;
151
152 ButtonClose := TButton.Create;
153 ButtonClose.Title := 'X';
154 ButtonClose.ParentControl := Self;
155 ButtonClose.OnClick := ButtonCloseClick;
156 ButtonClose.Visible := True;
157
158 ButtonMaximize := TButton.Create;
159 ButtonMaximize.Title := '^';
160 ButtonMaximize.ParentControl := Self;
161 ButtonMaximize.OnClick := ButtonMaximizeClick;
162 ButtonMaximize.Visible := True;
163
164 ButtonMinimize := TButton.Create;
165 ButtonMinimize.Title := '_';
166 ButtonMinimize.ParentControl := Self;
167 ButtonMinimize.OnClick := ButtonMinimizeClick;
168 ButtonMinimize.Visible := True;
169end;
170
171destructor TTitleBar.Destroy;
172begin
173 FreeAndNil(ButtonClose);
174 FreeAndNil(ButtonMaximize);
175 FreeAndNil(ButtonMinimize);
176 inherited;
177end;
178
179{ TCanvasWindow }
180
181procedure TCanvasWindow.DrawLine(P1, P2: TPosition; Color: TColor);
182begin
183 if Assigned(Window) and Assigned(Window.Screen) then
184 Window.Screen.Canvas.DrawLine(P1 + Window.Position, P2 + Window.Position, Color);
185end;
186
187procedure TCanvasWindow.DrawArea(Rect: TRectangle; Color: TColor);
188begin
189 if Assigned(Window) and Assigned(Window.Screen) then
190 Window.Screen.Canvas.DrawArea(TRectangle.Create(Rect.Position + Window.Position,
191 Rect.Size), Color);
192end;
193
194procedure TCanvasWindow.DrawText(P: TPosition; Color: TColor; Text: string);
195begin
196 if Assigned(Window) and Assigned(Window.Screen) then
197 Window.Screen.Canvas.DrawText(P + Window.Position, Color, Text);
198end;
199
200function TCanvasWindow.GetTextSize(Text: string): TSize;
201begin
202 if Assigned(Window) and Assigned(Window.Screen) then
203 Result := Window.Screen.Canvas.GetTextSize(Text);
204end;
205
206{ TWindow }
207
208procedure TWindow.SetScreen(AValue: TScreen);
209begin
210 if FScreen = AValue then Exit;
211 if Assigned(FScreen) then
212 FScreen.Windows.Remove(Self);
213 FScreen := AValue;
214 if Assigned(FScreen) then
215 FScreen.Windows.Add(Self);
216end;
217
218procedure TWindow.SetRectangle(AValue: TRectangle);
219begin
220 inherited;
221 TitleBar.Rectangle := TRectangle.Create(Position, TSize.Create(Size.Width, TitleBar.TitleHeight));
222end;
223
224procedure TWindow.SetVisible(AValue: Boolean);
225begin
226 inherited;
227 if not Visible and Assigned(Screen) then
228 Screen.Paint;
229end;
230
231procedure TWindow.HandleMessage(Message: TMessage);
232begin
233 if Message is TMessageWindowClose then begin
234 Free;
235 end else
236 if Message is TMessageWindowMaximize then begin;
237 Rectangle := TRectangle.Create(TPosition.Create(0, 0), Screen.Size);
238 Paint;
239 end;
240end;
241
242procedure TWindow.MouseButtonDown(Pos: TPosition; Button: TMouseButton);
243begin
244 inherited;
245 TitleBar.MouseButtonDown(Pos, Button);
246end;
247
248procedure TWindow.MouseButtonUp(Pos: TPosition; Button: TMouseButton);
249begin
250 inherited;
251 TitleBar.MouseButtonUp(Pos, Button);
252end;
253
254procedure TWindow.Close;
255begin
256 TApplication(Application).MessageQueue.PostMessage(Self, TMessageWindowClose.Create);
257end;
258
259procedure TWindow.Maximize;
260begin
261 TApplication(Application).MessageQueue.PostMessage(Self, TMessageWindowMaximize.Create);
262end;
263
264procedure TWindow.Focus;
265begin
266 if not Focused then begin
267 Screen.Windows.Move(Screen.Windows.IndexOf(Self), Screen.Windows.Count - 1);
268 Paint;
269 end;
270end;
271
272procedure TWindow.Paint;
273begin
274 if Visible then begin
275 Canvas.DrawArea(TRectangle.Create(TPosition.Create(0, 0), Size), clGray);
276 Canvas.DrawFrame(TRectangle.Create(TPosition.Create(0, 0), Size), clWhite);
277 Canvas.DrawLine(TPosition.Create(0, TitleBar.TitleHeight),
278 TPosition.Create(Size.Width, TitleBar.TitleHeight), clWhite);
279 Canvas.DrawText(TPosition.Create(8, 4), clWhite, Title);
280 TitleBar.Paint;
281 end;
282 inherited;
283end;
284
285function TWindow.Focused: Boolean;
286begin
287 Result := Screen.Windows.IndexOf(Self) = Screen.Windows.Count - 1;
288end;
289
290constructor TWindow.Create;
291begin
292 inherited;
293 FreeAndNil(Canvas);
294 Canvas := TCanvasWindow.Create;
295 TCanvasWindow(Canvas).Window := Self;
296 TitleBar := TTitleBar.Create;
297 TitleBar.Window := Self;
298 TitleBar.Visible := True;
299end;
300
301destructor TWindow.Destroy;
302begin
303 Visible := False;
304 FreeAndNil(TitleBar);
305 Screen := nil;
306 inherited;
307end;
308
309{ TScreen }
310
311procedure TScreen.MouseButtonDown(Pos: TPosition; Button: TMouseButton);
312var
313 I: Integer;
314 Window: TWindow;
315begin
316 for I := Windows.Count - 1 downto 0 do begin
317 Window := Windows[I];
318 if TRectangle.Create(Window.Position - TPosition.Create(Window.BorderGrabWidth div 2, 0),
319 TSize.Create(Window.BorderGrabWidth, Window.Size.Height)).Contains(Pos) then begin
320 GrabMousePosition := Pos;
321 GrabWindowRectangle := Window.Rectangle;
322 GrabWindow := Window;
323 GrabWindowSide := wsLeft;
324 GrabActive := True;
325 end else
326 if TRectangle.Create(Window.Position - TPosition.Create(0, Window.BorderGrabWidth div 2),
327 TSize.Create(Window.Size.Width, Window.BorderGrabWidth)).Contains(Pos) then begin
328 GrabMousePosition := Pos;
329 GrabWindowRectangle := Window.Rectangle;
330 GrabWindow := Window;
331 GrabWindowSide := wsTop;
332 GrabActive := True;
333 end else
334 if TRectangle.Create(Window.Position + TPosition.Create(Window.Size.Width, 0) - TPosition.Create(Window.BorderGrabWidth div 2, 0),
335 TSize.Create(Window.BorderGrabWidth, Window.Size.Height)).Contains(Pos) then begin
336 GrabMousePosition := Pos;
337 GrabWindowRectangle := Window.Rectangle;
338 GrabWindow := Window;
339 GrabWindowSide := wsRight;
340 GrabActive := True;
341 end else
342 if TRectangle.Create(Window.Position + TPosition.Create(0, Window.Size.Height) - TPosition.Create(0, Window.BorderGrabWidth div 2),
343 TSize.Create(Window.Size.Width, Window.BorderGrabWidth)).Contains(Pos) then begin
344 GrabMousePosition := Pos;
345 GrabWindowRectangle := Window.Rectangle;
346 GrabWindow := Window;
347 GrabWindowSide := wsBottom;
348 GrabActive := True;
349 end else
350 if TRectangle.Create(Window.Position, TSize.Create(Window.Size.Width, Window.TitleBar.TitleHeight)).Contains(Pos) then begin
351 GrabMousePosition := Pos;
352 GrabWindowRectangle := Window.Rectangle;
353 GrabWindow := Window;
354 GrabWindowSide := wsNone;
355 GrabActive := True;
356 end;
357 if Window.Rectangle.Contains(Pos) then begin
358 Window.Focus;
359 Window.MouseButtonDown(Pos - Window.Position, Button);
360 Break;
361 end;
362 end;
363end;
364
365procedure TScreen.MouseButtonUp(Pos: TPosition; Button: TMouseButton);
366var
367 I: Integer;
368 Window: TWindow;
369begin
370 if GrabActive then begin
371 GrabActive := False;
372 GrabWindow := nil;
373 end;
374 for I := Windows.Count - 1 downto 0 do begin
375 Window := Windows[I];
376 if Window.Rectangle.Contains(Pos) then begin
377 Window.MouseButtonUp(Pos - Window.Position, Button);
378 Break;
379 end;
380 end;
381end;
382
383procedure TScreen.MouseMove(Pos: TPosition);
384var
385 I: Integer;
386begin
387 if GrabActive then begin
388 if GrabWindowSide = wsNone then
389 GrabWindow.Position := GrabWindowRectangle.Position + (Pos - GrabMousePosition)
390 else if GrabWindowSide = wsLeft then
391 GrabWindow.Rectangle := TRectangle.Create(GrabWindowRectangle.Position + TPosition.Create(Pos.Left - GrabMousePosition.Left, 0),
392 GrabWindowRectangle.Size - TSize.Create(Pos.Left - GrabMousePosition.Left, 0))
393 else if GrabWindowSide = wsTop then
394 GrabWindow.Rectangle := TRectangle.Create(GrabWindowRectangle.Position + TPosition.Create(0, Pos.Top - GrabMousePosition.Top),
395 GrabWindowRectangle.Size - TSize.Create(0, Pos.Top - GrabMousePosition.Top))
396 else if GrabWindowSide = wsRight then
397 GrabWindow.Rectangle := TRectangle.Create(GrabWindowRectangle.Position,
398 GrabWindowRectangle.Size + TSize.Create(Pos.Left - GrabMousePosition.Left, 0))
399 else if GrabWindowSide = wsBottom then
400 GrabWindow.Rectangle := TRectangle.Create(GrabWindowRectangle.Position,
401 GrabWindowRectangle.Size + TSize.Create(0, Pos.Top - GrabMousePosition.Top));
402 Paint;
403 end;
404 for I := Windows.Count - 1 downto 0 do begin
405 if Windows[I].Rectangle.Contains(Pos) then begin
406 Windows[I].MouseMove(Pos - Windows[I].Position);
407 Break;
408 end;
409 end;
410end;
411
412procedure TScreen.SetMouse(AValue: TMouse);
413begin
414 if FMouse = AValue then Exit;
415 if Assigned(AValue) then begin
416 AValue.OnButtonDown := nil;
417 AValue.OnButtonUp := nil;
418 AValue.OnMove := nil;
419 end;
420 FMouse := AValue;
421 if Assigned(AValue) then begin
422 AValue.OnButtonDown := MouseButtonDown;
423 AValue.OnButtonUp := MouseButtonUp;
424 AValue.OnMove := MouseMove;
425 end;
426end;
427
428procedure TScreen.Paint;
429var
430 I: Integer;
431begin
432 Canvas.DrawArea(TRectangle.Create(TPosition.Create(0, 0), Size), clBlack);
433 for I := 0 to Windows.Count - 1 do
434 Windows[I].Paint;
435end;
436
437function TScreen.CreateWindow(Title: string): TWindow;
438begin
439 Result := TWindow.Create;
440 Result.Screen := Self;
441 Result.Title := Title;
442 Result.Rectangle := TRectangle.Create(TPosition.Create(10, 10), TSize.Create(400, 300));
443 Result.Visible := True;
444end;
445
446constructor TScreen.Create;
447begin
448 Windows := TObjectList<TWindow>.Create;
449 Windows.OwnsObjects := False;
450 Canvas := TCanvas.Create;
451end;
452
453destructor TScreen.Destroy;
454var
455 I: Integer;
456begin
457 for I := Windows.Count - 1 downto 0 do
458 Windows[I].Free;
459 FreeAndNil(Windows);
460 FreeAndNil(Canvas);
461 inherited;
462end;
463
464end.
465
466
Note: See TracBrowser for help on using the repository browser.