1 // Written in the D programming language. 2 /++ 3 + Authors: KanzakiKino 4 + Copyright: KanzakiKino 2018 5 + License: LGPL-3.0 6 ++/ 7 module w4d.widget.mdi.host; 8 import w4d.style.color, 9 w4d.style.widget, 10 w4d.task.window, 11 w4d.widget.mdi.layout, 12 w4d.widget.base, 13 w4d.exception; 14 import gl3n.linalg; 15 import std.algorithm, 16 std.array; 17 18 /// A host widget for MDI. 19 class MdiHostWidget : Widget 20 { 21 protected MdiClient[] _clients; 22 /// Child clients. 23 @property clients () { return _clients; } 24 25 /// 26 override @property Widget[] children () 27 { 28 return _clients.map!"a.widget".array; 29 } 30 31 /// 32 this () 33 { 34 super(); 35 setLayout!MdiLayout(); 36 37 _clients = []; 38 } 39 40 /// Adds the client widget. 41 void addClient ( MdiClient cli ) 42 { 43 enforce( cli, "The client is invalid." ); 44 cli.setHost( this ); 45 _clients ~= cli; 46 infectWindowContext(); 47 48 unfocusAllClients(); 49 cli.widget.enableState( WidgetState.Focused ); 50 } 51 /// Removes the client widget. 52 void removeClient ( MdiClient cli ) 53 { 54 _context.forget( cli.widget ); 55 _clients = _clients.remove!( x => x is cli ); 56 } 57 58 protected void unfocusAllClients () 59 { 60 foreach ( cli; _clients ) { 61 cli.widget.disableState( WidgetState.Focused ); 62 } 63 } 64 /// Focuses to the client. 65 void focusClient ( MdiClient cli ) 66 { 67 enforce( cli, "The client is invalid." ); 68 removeClient( cli ); 69 addClient( cli ); 70 } 71 72 /// 73 override @property bool needLayout () 74 { 75 return _needLayout; 76 } 77 /// Re-layouts child clients only that need layout. 78 void layoutQuickly () 79 { 80 auto pos = style.clientLeftTop; 81 auto size = style.box.clientSize; 82 83 children.filter!"a.needLayout"(). 84 each!( x => x.layout(pos,size) ); 85 } 86 87 /// 88 override void draw ( Window w, ColorSet parent ) 89 { 90 layoutQuickly(); 91 92 auto leftTop = style.translate + 93 style.box.borderInsideLeftTop; 94 95 w.clip.pushRect( leftTop, 96 style.box.borderInsideSize ); 97 super.draw( w, parent ); 98 w.clip.popRect(); 99 } 100 } 101 102 /// An interface of clients for MDI.. 103 interface MdiClient 104 { 105 /// Position of the client. 106 @property vec2 pos (); 107 /// Size of the client. 108 @property vec2 size (); 109 110 /// This property returns thiself that is casted to Widget. 111 /// To prove the casting is safe. 112 @property Widget widget (); 113 114 /// Changes the host widget. 115 void setHost ( MdiHostWidget ); 116 }