OSDN Git Service

Collect distributable package files in user specified directory.
[mingw/mingw-get.git] / src / pkgview.cpp
1 /*
2  * pkgview.cpp
3  *
4  * $Id$
5  *
6  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
7  * Copyright (C) 2012, 2013, MinGW.org Project
8  *
9  *
10  * Implementation of the layout controller for the main mingw-get
11  * application window.
12  *
13  *
14  * This is free software.  Permission is granted to copy, modify and
15  * redistribute this software, under the provisions of the GNU General
16  * Public License, Version 3, (or, at your option, any later version),
17  * as published by the Free Software Foundation; see the file COPYING
18  * for licensing details.
19  *
20  * Note, in particular, that this software is provided "as is", in the
21  * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
22  * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
23  * PARTICULAR PURPOSE.  Under no circumstances will the author, or the
24  * MinGW Project, accept liability for any damages, however caused,
25  * arising from the use of this software.
26  *
27  */
28 #include "guimain.h"
29 #include "pkgbase.h"
30 #include "dmh.h"
31
32 using WTK::StringResource;
33 using WTK::HorizontalSashWindowMaker;
34 using WTK::VerticalSashWindowMaker;
35
36 /* The main application window is divided into two
37  * horizontally adjustable sash panes; the following
38  * three constants specify the starting position for
39  * the sash bar, and the range over which it may be
40  * moved, as fractions of the width of the window,
41  * measured from its left hand side.
42  */
43 static const double HSASH_MIN_POS = 0.10;
44 static const double HSASH_INIT_POS = 0.20;
45 static const double HSASH_MAX_POS = 0.40;
46
47 /* The rightmost of these sash panes is further
48  * subdivided into two vertically adjustable panes;
49  * the following three constants similarly specify the
50  * initial position for the sash bar, and its range of
51  * adjustment, as fractions of the main window height,
52  * measured from its top edge.
53  */
54 static const double VSASH_MIN_POS = 0.25;
55 static const double VSASH_INIT_POS = 0.30;
56 static const double VSASH_MAX_POS = 0.60;
57
58 HWND AppWindowMaker::Create( const char *class_name, const char *caption )
59 {
60   /* A thin wrapper around the generic main window Create() function;
61    * it initialises the diagnostic message handler, and registers the
62    * requisite window class, before delegating creation of the main
63    * application window to the generic function.
64    */
65   dmh_init( DMH_SUBSYSTEM_GUI, class_name );
66   WTK::WindowClassMaker( AppInstance, ID_MAIN_WINDOW ).Register( class_name );
67   return WTK::MainWindowMaker::Create( class_name, caption );
68 }
69
70 long AppWindowMaker::OnCreate()
71 {
72   /* Handler for creation of the top-level application window;
73    * begin by initialising the sash window controls to support the
74    * desired three-pane sash window layout.
75    */
76   HorizontalSash = new HorizontalSashWindowMaker( ID_HORIZONTAL_SASH,
77       AppWindow, AppInstance, HSASH_MIN_POS, HSASH_INIT_POS, HSASH_MAX_POS
78     );
79   VerticalSash = new VerticalSashWindowMaker( ID_VERTICAL_SASH,
80       AppWindow, AppInstance, VSASH_MIN_POS, VSASH_INIT_POS, VSASH_MAX_POS
81     );
82
83   /* Assign the preferred font for use in the main window, falling
84    * back to the system default, if the choice is unavailable.
85    */
86   LOGFONT font_info;
87   HFONT font = DefaultFont;
88   GetObject( font, sizeof( LOGFONT ), &font_info );
89   strcpy( (char *)(&(font_info.lfFaceName)),
90       StringResource( AppInstance, ID_FONT_PREF )
91     );
92   if( (font = CreateFontIndirect( &font_info )) != NULL )
93   {
94     /* The preferred font choice is available; we may delete the
95      * object reference for the system default, then assign our
96      * preference in its place.
97      */
98     DeleteObject( DefaultFont );
99     DefaultFont = font;
100   }
101
102   /* Report that we've successfully handled the window set-up.
103    */
104   return EXIT_SUCCESS;
105 }
106
107 #if 0
108 /* FIXME: this stub implementation has been superseded by an
109  * alternative implementation in pkgdata.cpp; eventually, this
110  * may itself be superseded, and may migrate elsewhere, perhaps
111  * even back to here.
112  */
113 long AppWindowMaker::OnNotify( WPARAM client_id, LPARAM data )
114 {
115   /* Handler for notifications received from user controls; for now
116    * we simply quash any of these which we might receive.
117    */
118   return EXIT_SUCCESS;
119 }
120 #endif
121
122 long AppWindowMaker::OnSize( WPARAM mode, int width, int height )
123 {
124   /* Handler for WM_SIZE event, applied to main application window;
125    * we delegate to the LayoutController, to place, resize, and update
126    * the view for each child window pane, such that they fit within,
127    * and fill the main window's client area.
128    */
129   RECT ClientArea;
130   GetClientRect( AppWindow, &ClientArea );
131   EnumChildWindows( AppWindow, LayoutController, (LPARAM)(&ClientArea) );
132   return EXIT_SUCCESS;
133 }
134
135 int CALLBACK AppWindowMaker::LayoutController( HWND pane, LPARAM region )
136 {
137   /* The LayoutController provides a windows API callback hook, to
138    * service the WM_SIZE event; implemented as a static method...
139    */
140   HWND parent;
141   if( (parent = GetParent( pane )) != NULL )
142   {
143     /* ...it must retrieve an instance pointer to the C++ class
144      * object associated with the window to be laid out, then it
145      * may delegate the actual layout duty to the (non-static)
146      * LayoutEngine method associated with this object.
147      */
148     AppWindowMaker *p;
149     if( (p = GetAppWindow( parent )) != NULL )
150       return p->LayoutEngine( pane, region );
151   }
152   return TRUE;
153 }
154
155 int AppWindowMaker::LayoutEngine( HWND pane, LPARAM region )
156 {
157   /* Formal implementation for the LayoutController; this computes
158    * the positions and sizes for each of the panes and sash bars, to
159    * create a three pane layout similar to:
160    *
161    *         +----------+----------------------------+
162    *         |          |                            |
163    *         |   TREE   |       LIST VIEW PANE       |
164    *         |          |                            |
165    *         |   VIEW   +----------------------------+
166    *         |          |                            |
167    *         |   PANE   |   TABBED DATA-SHEET PANE   |
168    *         |          |                            |
169    *         |          |                            |
170    *         +----------+----------------------------+
171    */
172   long pane_id;
173
174   int pane_top = ((LPRECT)(region))->top;
175   int pane_left = ((LPRECT)(region))->left;
176   int pane_height = ((LPRECT)(region))->bottom - pane_top;
177   int pane_width = ((LPRECT)(region))->right - pane_left;
178
179   pane_top = pane_left = 0;
180   switch( pane_id = GetWindowLong( pane, GWL_ID ) )
181   {
182     /* Each of the panes and sashes is computed individually, in the
183      * following order:
184      */
185     case ID_PACKAGE_TREEVIEW:
186       /* Left hand pane; occupies the full height of the parent window,
187        * and shares its top-left co-ordinate position, with width set to
188        * the fraction of the parent's width specified as...
189        */
190       pane_width = HorizontalSash->Displacement( pane_width );
191       break;
192
193     case ID_PACKAGE_LISTVIEW:
194       /* Upper right hand pane; occupies the full width of the parent
195        * window which remains to the right of the tree view, (after an
196        * allowance for a small gap to accommodate the sash bar has been
197        * deducted); its upper edge is co-incident with the top of the
198        * parent, and its height is set to the fraction of the parent's
199        * height specified as...
200        */
201       pane_height = VerticalSash->Displacement( pane_height );
202       pane_left = HorizontalSash->Displacement( pane_width ) + SASH_BAR_THICKNESS;
203       pane_width -= pane_left;
204       break;
205
206     case ID_PACKAGE_TABPANE:
207     case ID_PACKAGE_TABCONTROL:
208     case ID_PACKAGE_DATASHEET:
209       /* Lower right hand pane; occupies the remaining area of the parent,
210        * to the right of the tree view pane, and below the list view, again
211        * with allowance for small gaps to the left and above, to accommodate
212        * the sash bars separating it from the adjacent panes.
213        */
214       pane_top = VerticalSash->Displacement( pane_height ) + SASH_BAR_THICKNESS;
215       pane_left = HorizontalSash->Displacement( pane_width ) + SASH_BAR_THICKNESS;
216       if( pane_id == ID_PACKAGE_TABCONTROL )
217       {
218         /* Shift the tab control window, and shrink it, so that it doesn't
219          * occlude the border surrounding the underlying tab pane window.
220          */
221         ++pane_left; ++pane_top; --pane_width; --pane_height;
222       }
223       else if( pane_id == ID_PACKAGE_DATASHEET )
224       {
225         /* Leave the data sheet window at the full width of the tab pane,
226          * but adjust its height and top edge position so that it appears
227          * below to tabs; (its own border will appear in place of the tab
228          * pane border, where they overlap.
229          */
230         RECT frame;
231         frame.top = pane_top;
232         frame.left = pane_left;
233         frame.right = pane_left + pane_width;
234         frame.bottom = pane_top + pane_height;
235         TabCtrl_AdjustRect( PackageTabControl, FALSE, &frame );
236         pane_top = frame.top - 1;
237       }
238       /* Adjust height and width to fill the space below and to the right
239        * of the two sash bars.
240        */
241       pane_height -= pane_top; pane_width -= pane_left;
242       break;
243
244     case ID_HORIZONTAL_SASH:
245       /* A slim window, placed to the right of the tree view pane, and
246        * occupying the full height of the parent window, representing the
247        * vertical sash bar, (which may be moved horizontally), and which
248        * separates the tree view pane from the list view and the tabbed
249        * data sheet panes.
250        */
251       pane_left = HorizontalSash->Displacement( pane_width ) - 1;
252       pane_width = 1 + SASH_BAR_THICKNESS;
253       break;
254
255     case ID_VERTICAL_SASH:
256       /* A slim window, placed below PANE TWO, and occupying the parent
257        * to the same width as PANE TWO and PANE THREE, representing the
258        * horizontal sash bar, (which may be moved vertically), which
259        * separates PANE TWO from PANE THREE.
260        */
261       pane_top = VerticalSash->Displacement( pane_height ) - 1;
262       pane_left = HorizontalSash->Displacement( pane_width ) + SASH_BAR_THICKNESS;
263       pane_height = 1 + SASH_BAR_THICKNESS; pane_width -= pane_left;
264       break;
265   }
266   /* Having computed the size and position for the pane or sash which
267    * is the target of the current call, move it into place within the
268    * parent window, and cause it to be displayed.
269    */
270   MoveWindow( pane, pane_left, pane_top, pane_width, pane_height, TRUE );
271   ShowWindow( pane, SW_SHOW );
272   return TRUE;
273 }
274
275 /* $RCSfile$: end of file */