Creation of a UserControl: Collapsible Panel: Difference between revisions

From OpenPetra Wiki
Jump to navigation Jump to search
No edit summary
(added the requirement of having panel work in design view)
 
(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
==Introduction==
==Introduction==
There are three different styles in which a 'Collapsible Panel' should be able to be displayed in openPETRA (see screenshots on the side).
There are three different styles in which a 'Collapsible Panel' should be able to be displayed in openPETRA when collapsing vertically and two different styles when collapsing horizontally (see screenshots on the side).


[[File:Task_Panel_Sample_1a_-_Accordion_Panel_Demo.png|100px|thumb|right|Inside the Accordion Panel]]
[[File:Task_Panel_Sample_1a_-_Accordion_Panel_Demo.png|100px|thumb|right|Combined: One vsHorizontalCollapse-Style Collapsible Panel (as 'Navigation Panel' in openPETRA Main Menu) hosting several vsAccordionPanel-Style Collapsible Panels]]
[[File:Task_Panel_Sample_1a_-_Accordion_Panel_Demo_collapsed.png|100px|thumb|right|Inside the Accordion Panel - collapsed]]
[[File:Task_Panel_Sample_1a_-_Accordion_Panel_Demo_collapsed.png|100px|thumb|right|Combined: One vsHorizontalCollapse-Style Collapsible Panel (as 'Navigation Panel' in openPETRA Main Menu) hosting several vsAccordionPanel-Style Collapsible Panels - topmost vsAccordionPanel-Style Collapsible Panel collapsed]]


[[File:Task_Panel_Sample_3_-_Task_Panel.png|100px|thumb|right|Vertical: Inside a Task Panel]]
[[File:Task_Panel_Sample_3_-_Task_Panel.png|100px|thumb|right|Vertical: Several vsTaskPanel-Style Collapsible Panels]]
[[File:Task_Panel_Sample_3_-_Task_Panel_collapsed.png|100px|thumb|right|Vertical: Inside a Task Panel - collapsed]]
[[File:Task_Panel_Sample_3_-_Task_Panel_collapsed.png|100px|thumb|right|Vertical: Several vsTaskPanel-Style Collapsible Panels - topmost vsTaskPanel-Style Collapsible Panel collapsed]]
[[File:TaskPanel_WindowsExplorer_WinXP.jpg|100px|thumb|right|Vertical: Task Panel, WinXP Explorer style (this is the 'Visual Style' we roughly want to mimic with vsTaskPanel, not the 'orangey' one above)]]


[[File:Task_Panel_Sample_2_-_Folding_Panel.png|250px|thumb|right|Vertical: Dashboards in Main Menu Task Area]]
[[File:Task_Panel_Sample_2_-_Folding_Panel_collapsed.png|250px|thumb|right|Vertical: Dashboards in Main Menu Task Area - collapsed]]


[[File:Collapsible_Panel_Sample_1_-To-Do_Bar.png|250px|thumb|right|Horizontal: To-Do Bar]]
[[File:Task_Panel_Sample_2_-_Folding_Panel.png|250px|thumb|right|Vertical: A vsDashboard-Style Collapsible Panel (as 'Dashboard' in openPETRA Main Menu Task Area, hosting a UserControl)]]
[[File:Collapsible_Panel_Sample_1_-To-Do_Bar_collapsed.png|250px|thumb|right|Horizontal: To-Do Bar - collapsed]]
[[File:Task_Panel_Sample_2_-_Folding_Panel_collapsed.png|250px|thumb|right|Vertical: A vsDashboard-Style Collapsible Panel (as 'Dashboard' in openPETRA Main Menu Task Area, hosting a UserControl) - collapsed]]
[[File:Collapsible_Panel_Sample_2_-_Navigation_Pane_collapsed.png|250px|thumb|right|Horizontal: Accordion Panel - collapsed]]
 
[[File:Collapsible_Panel_Sample_1_-To-Do_Bar.png|250px|thumb|right|Horizontal: A vsHorizontalCollapse-Style Collapsible Panel (as 'To-Do Bar' in openPETRA Main Menu Task Area)]]
[[File:Collapsible_Panel_Sample_1_-To-Do_Bar_collapsed.png|250px|thumb|right|Horizontal: A vsHorizontalCollapse-Style Collapsible Panel (as 'To-Do Bar' in openPETRA Main Menu Task Area) - collapsed]]
[[File:Collapsible_Panel_Sample_2_-_Navigation_Pane_collapsed.png|250px|thumb|right|Horizontal: A vsHorizontalCollapse-Style Collapsible Panel (as 'Navigation Panel' in openPETRA Main Menu) - collapsed]]
 
[[File:Task_Panel_Sample_4_-_Shepherd_Page_Panel.png|100px|thumb|right|Horizontal: A vsShepherd-Style Collapsible Panel (inside an openPETRA Shepherd [no collapse button shown here, though!])]]
 
 
'''With 'Collapsible Panel' we mean each of the panels that ''host'' either a 'Task List' (holding several Task Items), or any UserControl to be able to show custom content.'''
 
The ''main feature'' of a Collapsible Panel is that it can be expanded or collapsed - either Top, Bottom, Left, or Right depending on what the ".Dock" property is set to.
* ''Top Collapsing'' (see first five screenshots on the side)
** <s>In the collapsed state only the Title Panel (a small panel containing a title text and a Button for expanding it and an optional Icon) is left. In this state the Collapsible Panel does not take up much space on the screen.</s>
** <s>In the expanded state the Title Panel remains and in addition to that the actual content of the Collapsible Panel (a Task List or a UserControl) is shown. In this state the Collapsible Panel takes up at least as much space on the screen as its contents plus the space the Title Panel needs.</s>
** Note, that technically it does not expand to "at least as much space on the screen as its contents". Rather, it expands to the defined size of the panel, which presumably was set correctly by the user of the panel. This is also true for all following directions.
** The button icons do not refresh correctly when collapsed/expanded. (see manual GUI tests).
* <s>''Bottom Collapsing'' (see the next two screenshots on the side)</s>
** <s>In the collapsed state only the Title Panel (a small panel containing a title text and a Button for expanding it and an optional Icon) is left. In this state the Collapsible Panel does not take up much space on the screen.</s>
** <s>In the expanded state the Title Panel remains and in addition to that the actual content of the Collapsible Panel (a Task List or a UserControl) is shown. In this state the Collapsible Panel takes up at least as much space on the screen as its contents plus the space the Title Panel needs.</s>
* ''Right Collapsing'' (see next two screenshots on the side)
** <s>In the expanded state the Collapsible Panel is as wide as the content it hosts requires and as high as the content it hosts requires plus the space the Title Panel needs. The actual content of the Collapsible Panel (a Task List or a UserControl) is shown under the the Title Panel.</s>
** <s>In the collapsed state the Collapsible Panel is just a narrow panel that doesn't show the content it hosts and is still as high as the content it hosts requires  plus the space the Title Panel needs. In this state the Collapsible Panel does not take up much space on the screen. The Title Panel doesn't show the Title Text, but only a Button for expanding;</s>
** The Title Text is shown at a perpendicular angle underneath the Title Panel.
** The button icons do not refresh correctly when collapsed/expanded. (see manual GUI tests).
** Does the collapse icon need to appear on far left of Title when expanded??
* ''Left Collapsing'' (see last two screenshots on the side)
** <s>In the expanded state the Collapsible Panel is as wide as the content it hosts requires and as high as the content it hosts requires plus the space the Title Panel needs. The actual content of the Collapsible Panel (a Task List or a UserControl) is shown under the the Title Panel.</s>
** <s>In the collapsed state the Collapsible Panel is just a narrow panel that doesn't show the content it hosts and is still as high as the content it hosts requires plus the space the Title Panel needs. In this state the Collapsible Panel does not take up much space on the screen. The Title Panel doesn't show the Title Text, but only a Button for expanding;</s>
** The Title Text is shown at a perpendicular angle underneath the Title Panel.


With 'Collapsible Panel' we mean each of the panels that host either a list of Task Items, or a UserControl with custom content (especially in case of Dashboards, but not limited to them).


The ''main feature'' of a Collapsible Panel is that it can be expanded or collapsed - either vertically or horizontally.
* ''Vertical Collapsing'' (see first six screenshots on the side)
** In the collapsed state only the Title Panel (a small panel containing a title text and a Button for expanding it and an optional Icon) is left. In this state the Collapsible Panel does not take up much space on the screen.
** In the expanded state the Title Panel remains and in addition to that the actual content of the Collapsible Panel (a Task List or a UserControl) is shown. In this state the Collapsible Panel takes up at least as much space on the screen as its contents plus the space the Title Panel needs.
* ''Horizontal Collapsing'' (see last three screenshots on the side)
** In the expanded state the Collapsible Panel is as wide and as high as the content it hosts requires and the actual content of the Collapsible Panel (a Task List or a UserControl) is shown under the the Title Panel.
** In the collapsed state the Collapsible Panel is just a narrow panel that doesn't show the content it hosts and is still as high as the content it hosts requires. In this state the Collapsible Panel does not take up much space on the screen. The Title Panel doesn't show the Title Text, but only a Button for expanding; instead, the Title Text is shown at an 90 degree angle underneath the Title Panel.
The ''other features'' of a Collapsible Panel are
The ''other features'' of a Collapsible Panel are
* it supports different 'Styles', as shown in the screenshots along the side;
* it supports different 'Styles', as shown in the screenshots along the side;
* it can host either a '[[Creation of a UserControl: Task List |Task List]]' or an arbitrary UserControl as a content;
* <s>it can host either a '[[Creation of a UserControl: Task List |Task List]]' or an arbitrary UserControl as a content;</s>
* it auto-sizes in both vertical and horizontal direction to always fit the size of the content.
* it auto-sizes in both vertical and horizontal direction to always fit the size of the content.


Line 32: Line 51:
There is another Project, '[[Creation of a UserControl: Task List]]', whose UserControl is specifically designed to be hosted inside a Collapsible Panel.
There is another Project, '[[Creation of a UserControl: Task List]]', whose UserControl is specifically designed to be hosted inside a Collapsible Panel.


Note: The corresponding Bug (=Feature Request) is [https://sourceforge.net/apps/mantisbt/openpetraorg/view.php?id=205 Bug #205].
Notes:  
 
* The corresponding Bug (=Feature Request) is [https://sourceforge.net/apps/mantisbt/openpetraorg/view.php?id=205 Bug #205].
* The Bazaar Branch in which the development is to happen is called 'dev_0000205_studentsJ2011_usercontrol_collapsiblepanel'.


==Desired Outcome==
==Desired Outcome==
* Creation of ''one'' UserControl which acts as a 'Collapsible Panel' whose 'look and feel' can be set to ''three different styles'', as shown in the screenshots along the side.  
* Creation of ''one'' UserControl which acts as a 'Collapsible Panel' whose 'look and feel' can be set to ''five different styles'', as shown in the screenshots along the side.  
** The different styles will need to affect  
** The different styles will need to affect  
*** the Title Panel
*** the Title Panel
Line 46: Line 66:
*** the Content Panel
*** the Content Panel
**** gradient colours of the Content Panel (which hosts the actual content, e.g. Task List or a UserControl) (see screenshot 'Inside the Accordion Panel' along the side)
**** gradient colours of the Content Panel (which hosts the actual content, e.g. Task List or a UserControl) (see screenshot 'Inside the Accordion Panel' along the side)
* The UserContol needs to collapse when the collapse/expand Button is clicked and it is currently expanded, and it needs to expand when the collapse/expand Button is clicked and it is currently collapsed.
* Expand/Collapse
** <s>The UserContol needs to collapse when the collapse/expand Button is clicked and it is currently expanded, and it needs to expand when the collapse/expand Button is clicked and it is currently collapsed.</s>
** Vertical collapsing mode only: It shall also toggle its collapsed/expanded state if the Title Panel, the Title Text or the Title Icon is clicked.
** Vertical collapsing mode only: It shall also toggle its collapsed/expanded state if the Title Panel, the Title Text or the Title Icon is clicked.
** The Icon on the Title Button needs to change on toggling to show the correct Icon for the collapsed/expanded state
** The Icon on the Title Button needs to change on toggling to show the correct Icon for the collapsed/expanded state. This almost works. See the above instructions about "main funcitonality" (the bullets not not crossed out).
* The UserControl needs to support collapsing in either horizontal or vertical direction.
* The UserControl needs to support collapsing in either horizontal or vertical direction.
** When set up to collapse in horizontal direction
** When set up to collapse in horizontal direction
*** there needs to be an option to specify whether it collapses 'to the right' or 'to the left'. This will affect the horizontal position of the collapse/expand Button, which Icon is shown for collapsing/expanding and whether the Title Text is rotated 90 degrees or 180 degrees (compare screenshots 'Horizontal: To-Do Bar - collapsed' and 'Horizontal: Accordion Panel - collapsed').
*** <s>there needs to be an option to specify whether it collapses 'to the right' or 'to the left'.</s>
*** a Panel which can contain an arbitrary Control (which also can be a UserControl) needs to be shown on request and display the desired Control (Icon and text 'No Reminders.' in screenshot 'Horizontal: To-Do Bar - collapsed').
*** ... This will affect the horizontal position of the collapse/expand Button, which Icon is shown for collapsing/expanding and whether the Title Text is rotated 90 degrees or 180 degrees (compare screenshots 'Horizontal: To-Do Bar - collapsed' and 'Horizontal: Accordion Panel - collapsed').
*** <s>a Panel which can contain an arbitrary Control (which also can be a UserControl) needs to be shown on request and display the desired Control (Icon and text 'No Reminders.' in screenshot 'Horizontal: To-Do Bar - collapsed').</s>
*** it must be possible to limit the height of the internal Panel which shows rotated Title text to a certain number of pixels so that part of the hosted content is still visible (Icons for openPetra Modules in screenshot 'Horizontal: Accordion Panel - collapsed'). If its height isn't limited, this internal Panel shall fill the full height of the UserControl in order to hide the hosted content completely.
*** it must be possible to limit the height of the internal Panel which shows rotated Title text to a certain number of pixels so that part of the hosted content is still visible (Icons for openPetra Modules in screenshot 'Horizontal: Accordion Panel - collapsed'). If its height isn't limited, this internal Panel shall fill the full height of the UserControl in order to hide the hosted content completely.
* Dealing with hosted content
* <s>Dealing with hosted content</s>
** When the UserControl is hosting the '[[Creation of a UserControl: Task List |Task List]]', it needs to accept the Task Items as a single XmlNode and pass it on to the Task List.
** <s>When the UserControl is hosting the '[[Creation of a UserControl: Task List |Task List]]', it needs to accept the Task Items as a single XmlNode and pass it on to the Task List.</s>
** When the UserControl is hosting an arbitrary UserControl, it needs to accept information about it so it can instantiate it.
** <s>When the UserControl is hosting an arbitrary UserControl, it needs to accept information about it (the Namespace it is found in and its Class name) so it can instantiate it.</s>
** The UserControl needs to dynamically create the hosted content (a Task List or an arbitrary UserControl) the first time it is expanded.
** <s>The UserControl needs to dynamically create the hosted content (a Task List or an arbitrary UserControl) the first time it is expanded.</s>
*** This is in order to speed up the realisation (painting) of a screen that hosts a Collapsing Panel which is in its 'collapsed' state (only the Title Panel needs to be realised in this case!).
*** <s>This is in order to speed up the realisation (painting) of a screen that hosts a Collapsing Panel which is in its 'collapsed' state (only the Title Panel needs to be realised in this case!).</s>
* The UserControl needs to be able to auto-size itself in vertical and horizontal direction - depending on the size needed for hosting the Task List or a UserControl in the Content Panel.
* The UserControl needs to be able to auto-size itself in vertical and horizontal direction - depending on the size needed for hosting the Task List or a UserControl in the Content Panel. ~ I (sethb) did not explicitly test this in manual GUI tests.
* The UserControl needs to have a read-only Property 'IsCollapsed'. (This can be used by the screen which hosts this UserControl to inquire its state.)
* <s>The UserControl needs to have a read-only Property 'IsCollapsed'. (This can be used by the screen which hosts this UserControl to inquire its state.)</s>
* The UserControl needs to have Properties to set the Title Text and the optional Title Icon.
* <s>The UserControl needs to have Properties to set the Title Text</s>
* The UserControl needs to raise Events when it got Expanded or Collapsed.
* The UserControl needs to have Properties to set the optional Title Icon.
** On receiving those Events, the screen which hosts this UserControl do any necessary screen re-arrangement, or change the tick on a MenuItem, for example.
* <s>The UserControl needs to raise Events when it got Expanded or Collapsed.</s>
** <s>On receiving those Events, the screen which hosts this UserControl can do any necessary screen re-arrangement, or change the tick on a MenuItem, for example.</s>
* Navigation between the content hosted in the Content Panel (Task List or arbitrary UserControl) and the Title Panel needs to be possible by keyboard!  
* Navigation between the content hosted in the Content Panel (Task List or arbitrary UserControl) and the Title Panel needs to be possible by keyboard!  
** <CURSOR-UP> and <CURSOR-DOWN> keys for navigation  
** <CURSOR-UP> and <CURSOR-DOWN> keys for navigation  
*** 'Highlighting' of Title Text if the Focus is there
**** Highlighting should be done by painting a rectangle with dotted line around the Title Text
** <ENTER> and <SPACE> keys for changing the collapsed/expanded state if the Focus is on the Title Text
** <ENTER> and <SPACE> keys for changing the collapsed/expanded state if the Focus is on the Title Text
** 'Highlighting' of Title Text if the Focus is there
*** Highlighting should be done by painting a rectangle with dotted line around the Title Text
* Title Text will need to be able to show an underlined character (designated by an ampersand & sign in the text). If the user presses <ALT>+<{underlined character}>, the collapsed state shall be changed to expanded (only if the UserControl is currently collapsed) and the input Focus shall be given to the Content Panel.  
* Title Text will need to be able to show an underlined character (designated by an ampersand & sign in the text). If the user presses <ALT>+<{underlined character}>, the collapsed state shall be changed to expanded (only if the UserControl is currently collapsed) and the input Focus shall be given to the Content Panel.  
** See screenshot 'Menu Items in Accordion Panel' along the side (&General Ledger Collapsible Panel)
** See screenshot 'Menu Items in Accordion Panel' along the side (&General Ledger Collapsible Panel)
Line 75: Line 98:
* Public Methods for Disabling/Enabling and Hiding/Showing of a Collapsible Panel must be implemented.
* Public Methods for Disabling/Enabling and Hiding/Showing of a Collapsible Panel must be implemented.
** Method for Disabling needs to throw a custom Exception if it is called while the Collapsible Panel is expanded.
** Method for Disabling needs to throw a custom Exception if it is called while the Collapsible Panel is expanded.
 
* The UserControl ''needs to work'' with the 'Large Fonts (120 DPI)' display setting.
** If you can get it to work with any arbitrary DPI setting this would be good, but ''this isn't a requirement''.
* The UserControl ''should work'' on Linux and Mac OS X, if possible (''this isn't a requirement'').
** Don't spend too much time on this - if you can get it to work without too much effort then do it, otherwise just write down the problems you experience so we can follow it up in time.
** Test this only once a while during development - testing this shouldn't consume much time.
* ''OPTIONAL:'' Vertical collapsing mode only: Ability to display a 'x' button which would raise a custom Event. The screen or control which hosts the Collapsible Panel would make the Collapsible Panel invisible on receiving this Event (see screenshots for 'Task Panel' and 'To-Do Bar').
* Cooperating with the design view.
** In order for the Design view to be useful for programmers to use, the panel must cooperate with the design view mode. Therefore, it must be visible in design view. More specifically, if that is too cumbersome, as long as some placeholder is there in design view so that the positioning of other elements works that could work too, but you will need specific approval by Lead Developer to make sure that the nuances are correct.


==Outline of the Solution==
==Outline of the Solution==
Line 83: Line 113:


===Step 1===
===Step 1===
Start with an existing UserControl:
''Important: Follow the openPETRA '[[Coding Standard and Guidelines]]' for all code that you write!''
* Open the Ict.Common.Controls C# Project (located in \csharp\ICT\Common\Controls) and open the Class 'TPnlCollapsible' contained in file 'pnlCollapsible.cs'.
 
* This is a basic implementation of a 'Collapsible Panel' which collapses only in vertical direction.  
* Start with an existing UserControl
** Have a look how things are done.
** Open the Ict.Common.Controls C# Project (located in \csharp\ICT\Common\Controls) and open the Class 'TPnlCollapsible' contained in file 'pnlCollapsible.cs'.
** You can play around with that Panel by starting openPetra and clicking 'Find Partners' in the Task List on the right.
** This is a basic implementation of a 'Collapsible Panel' which collapses only in vertical direction.  
*** You won't be able to find any Partners at the moment as this is an empty openPETRA database, but the Collapsible Panel still works.
*** Have a good look how things are done and what is already implemented.
**** Note that the Panel can be expanded/collapsed by clicking its expand/collapse icon, by clicking anything else in the Title Panel, and by clicking the 'Partner Info' ToolBarButton and by checking/unchecking the 'View'->'Partner Info Panel' MenuItem.
*** You can play around with that Panel by starting openPetra and clicking 'Find Partners' in the Task List on the right.
* Extend the UserControl so that it can also expand and collapse in horizontal direction
**** You won't be able to find any Partners at the moment as this is an empty openPETRA database, but the Collapsible Panel still works.
** Add a public enum to that file, outside the Class definition.  
***** Note that the Panel can be expanded/collapsed by clicking its expand/collapse icon [REF], by clicking anything else in the Title Panel [REF], and by clicking the 'Partner Info' ToolBarButton and by checking/unchecking the 'View'->'Partner Info Panel' MenuItem.
 
* Extend the UserControl so that it can also expand and collapse in horizontal direction - BASIC [REF]
** Add a public enum to that file, outside the definition of the TPnlCollapsible Class.  
*** Name it 'TCollapseDirection'.  
*** Name it 'TCollapseDirection'.  
*** Add the following values: cdVertical, cdHorizontal
*** Add the following values: cdVertical, cdHorizontal
** Add a 'CollapseDirection' Property of Type 'TCollapseDirection'.
** Add a 'CollapseDirection' Property of Type 'TCollapseDirection'.
*** Implement the change of collapsing behaviour in a private Method that gets called from the 'setter' of this Property.
*** Implement the change of collapsing behaviour in a private Method that gets called from the 'setter' of this Property.
**** Among other things, the set of four Icons with arrows for collapsing/expanding need to be swapped with the other set of four icons
**** The set of four Icons with arrows for collapsing/expanding need to be swapped with the other set of four icons [REF]
***** For this, four new Icons need to be added to the ImageList 'imlUpDownArrows'. To do this, switch to the Designer View of the IDE and select the 'imlUpDownArrows' Control in the area on the bottom. Then click on the '...' button in the Properties Panel to edit the ImageList collection of Icons. Add four new Icons for the horizontal collapse mode (ask ChristianK for the icon files).
***** For this, four new Icons need to be added to the ImageList 'imlUpDownArrows'. To do this, switch to the Designer View of the IDE and select the 'imlUpDownArrows' Control in the area on the bottom. Then click on the '...' button in the Properties Panel to edit the ImageList collection of Icons. Add four new Icons for the horizontal collapse mode (ask ChristianK for the icon files).
**** Show/hide the Title Text in the Title Panel.
** The existing UserControl has hard-coded values for collapsed and expanded height (COLLAPSEDHEIGHT and EXPANDEDHEIGHT). For the moment we will use those for setting the collapsed and expanded width as well. This will be improved on in Step 2.
** The existing UserControl has hard-coded values for collapsed and expanded height (COLLAPSEDHEIGHT and EXPANDEDHEIGHT). For the moment we will use those for setting the collapsed and expanded width as well. This will be improved on in Step 2.
* Test and demonstrate this in a small test application, which you should create for that purpose.
* Test and demonstrate this in a small test application, which you should create for that purpose.
** The Test Application is to be created in the directory \csharp\ICT\Testing\Common\Controls (doesn't exist yet) and to be called 'ControlTestBench.sln'.
** The Test Application is to be created in the directory \csharp\ICT\Testing\Common\Controls (doesn't exist yet) and to be called 'ControlTestBench.sln'.
** It should have a main Form with some Buttons. Each of the Buttons should launch a test Form that is specific for a certain UserControl.
** It should have a main Form with some Buttons. Each of the Buttons should launch a test Form that is specific for a certain UserControl.
** Co-ordintate yourself with the creators of the '[[Creation of a UserControl: Task List|Task List]]' to ensure that only one of you creates that application - namely the one who gets to this step first.


===Step 2===
===Step 2===
TODO
* Add a public enum to the .cs file in which the TPnlCollapsible Class is found (=the file you are working with), outside the definition of the TPnlCollapsible Class.
** Name it 'THostedControlKind'.
** Add the following values: hckUserControl, hckTaskList
* Add a 'HostedControlKind' Property of Type 'THostedControlKind'.
** In the 'setter' of this Property set a Field of the Collapsible Panel class to the value that is passed in.
 
* Add ability to instantiate and host an ''arbitrary'' UserControl [REF]
** The current implementation simply exposes the 'pnlContent' Control so an inheritor can 'add' an arbitrary Control in it. Make 'pnlContent' Control private again (see also XML comment on pnlContent in the pnlContent.Designer.cs file).
** pnlContent should not need to be inherited from anymore to place arbitrary Controls on its Content Panel. Instead, pnlContent will need to get the ability to instantiate and host an ''arbitrary'' UserControl. This makes hosting a Collapsible Panel easier, is more flexible, and allows to encapsulate the logic for postponing the instantiation of the hosted UserControl until the point in time when the Collapsible Panel is actually expanded, therefore speeding up the realisation (painting) of a Form that hosts a collapsed Collapible Panel.
*** Add Properties 'UserControlNamespace' and 'UserControlClass', both of Type 'string'. They will need to be set by the Form or Control which hosts the Collapsible Panel. [REF]
**** In the 'setter' of both these Properties throw a ''custom'' Exception (which you shall specify in the same .cs file, but outside the definition of the TPnlCollapsible Class) if the 'HostedControlKind' Property is set to hckTaskList. This will tell the caller that the Control is set to host a Task List and therefore can't host a UserControl at the same time.
*** Add read-only Property 'UserControlInstance' of Type 'UserControl'. This will return null if the UserControl wasn't instantiated yet, and will return the actual instance of the dynamically created UserControl once it has been instantiated. (This instance can be casted to a specific Type by the Form or Control which hosts the Collapsible Panel and it can then call Methods or pass in values into Properties of that UserControl and receive Events from it.)
*** Add public Method 'RealiseUserControlNow()' to force the Collapsible Panel to create an instance of the UserControl when called (needed only in case the Form or Control which hosts the Collapsible Panel wants to create the instance while the Collapsible Panel is still closed. The Form or Control which hosts the Collapsible Panel might want to do this in a background thread to populate the UserControl [which might well load data from the DB] while the user isn't aware of it and so that it expands promptly once the user expands the Collapsible Panel).
*** Add private Method 'RealiseUserControl()'. It needs to be called from the public Method 'RealiseUserControlNow' and once the Collapsible Panel gets expanded ''for the first time''.
**** The first thing this Method needs to do is to check whether it has all the necessary information. Inspect the values of both the 'UserControlNamespace' and 'UserControlClass' Properties and check wheter they aren't String.Empty. Should one of them be String.Empty throw a System.ArgumentException, specifying the reason for it in it's String Argument.
**** This Method will utilise a .NET technique called 'Reflection' to load an Assembly (=DLL) which contains the Namespace specified with Property 'UserControlNamespace' and to then create an instance of the Class which is specified with Property 'UserControlClass'.
***** .NET Reflection ''is tricky''! You can find code that does something similar, although more complicated, in Method ''ExecuteAction'' in Class Ict.Common.Controls.TLstTask (found in \csharp\Ict\Common\Controls\lstTask.cs). (TLstTask is the Control on the right side of the openPETRA Main Menu that dynamically loads DLLs, instantiates openPETRA screen Classes and in the end shows openPETRA screens once the user clicks on a list item.)
****** The key commands in that Method are 'Assembly.LoadFrom' and 'Activator.CreateInstance'. Search for them in the Method and see how they are used. TLstTask caches Assemblies for re-use, you don't need to do that in this UserControl.
****** Try to write code that loads the correct assembly and instantiates the specified UserControl. You might want to 'google' for '.NET Reflection', 'Assembly.LoadFrom' and 'Activator.CreateInstance' to see how others are using them. If you get stuck, get ChristianK to help you - ''you shouldn't spend too much time on that basic, although very important, feature of the Collapsible Panel.''
****** Cast the created instance to Type UserControl and hold it in a Field (of Type UserControl) of the TPnlCollapsible Class.
 
* Add ability to instantiate and host a '[[Creation of a UserControl: Task List|Task List]]' [REF]
** Check with the creators of the Task List UserControl whether they are already past 'Step 1'. This would be a requirement for you to use it with the Collapsible Panel.
*** If it is past 'Step 1' then creators of the Task List should make a Commit to their Branch so you can merge it into your branch and use it with the Collapsible Panel.
*** If it isn't past 'Step 1' yet you can still add the Property 'TaskListNode' (see below) but you can't instantiate the Task List on expanding the Collapsible Panel (obviously). Check back with them regularly to see whether they are past 'Step 1'.
** Add Property 'TaskListNode' Property of type XmlNode. [REF]
*** In the 'setter' of this Property set a Field of the Collapsible Panel class to the value that is passed in, not the 'XmlNode' Property of the Task List instance, as that instance might not exist yet if the Collapsible Panel is collapsed when this Property is written to!
*** Throw a ''custom'' Exception (which you shall specify in the same .cs file, but outside the definition of the TPnlCollapsible Class) if the 'HostedControlKind' Property is set to hckUserControl. This will tell the caller that the Control is set to host a UserControl and therefore can't host a Task List at the same time.
** Add read-only Property 'TaskListInstance' of Type 'TTaskList'. This will return null if the Task List wasn't instantiated yet, and will return the actual instance of the dynamically created Task List once it has been instantiated. (This instance can be used by the Form or Control which hosts the Collapsible Panel to call Methods of that Task List instance, to set its Properties and to receive Events from it.)
 
* Dynamically create the hosted content (a Task List or an arbitrary UserControl) the first time the Collapsible Panel is expanded [REF]
** This will need to happen in the public Method 'Expand' which already exists in a very basic form.
** Add a 'switch' block in this Method which switches on the value of the 'HostedControlKind' Property and calls one of the following two new private Methods: InstantiateUserControl(), InstantiateTaskList().
*** The InstantiateUserControl Method simply needs to call the private Method 'RealiseUserControl()'.
*** The InstantiateTaskList Method will need to create an instance of Class 'TTaskList', set its 'TaskListNode' Property and hold it in a Field (of Type TTaskList) of the TPnlCollapsible Class.
* Test and demonstrate the new functionality in the test application.


===Step 3===
===Step 3===
TODO
* Add a Property 'Title Icon' of Type 'Image' to be able to show an optional Title Icon in the Title Panel [REF].
** In the 'setter':
*** If a non-null value is passed in, move the lblDetailHeading Control about 20 pixels to the right, add the Icon to pnlTitleText and set the Icon' Location.X value to the lblDetailHeading's Location.X original value.
*** If a null value is passed in, place the lblDetailHeading Control at its original location and hide the Icon (if it was ever instantiated in the first place).
 
* Add a 'VisualStyle' Property of Type 'TVisualStyles'.
** Note: The 'TVisualStyles' Class was created as part of Project 'Task List'. Merge code in from that Project's branch to get this Class.
** All five Visual Styles will be used by the Collapsible Panel UserControl.
* Implement the change of visual style in a private Method that gets called from the 'setter' of this Property.
** Restrict the choice of Visual Style as follows:
*** vsAccordionPanel, vsTaskPanel and vsDashboard can be used only if the Collapsible Panels collapses vertical.
*** vsHorizontalCollapse and vsShepherd can be used only if the Collapsible Panels collapses horizontal (see 'Horizontal: To-Do Bar' and 'Horizontal: Accordion Panel' screenshots).
*** Throw a custom Exception if the user tries to set a Visual Style that doesn't go with the TCollapseDirection value.
** Change of visual style needs to affect various things (e.g. font, title panel height, background, ...). See [REF] and screenshots along the side.
** Use UserControl 'Ict.Common.Controls.TPnlGradient' instead of a standard WinForms Panel for the Title Panel (pnlTitleText) to have a panel that supports a gradient background (see pnlContent which alread is a TPnlGradient).
 
* Add ability to auto-size itself in vertical and horizontal direction [REF].
** The UserControl already has the properties 'AutoSize' and 'AutoSizeMode' set correctly, so the basic .NET WinForm requirements for that ability should already be met (needs to be verified, though).
** When collapsing/expanding the UserControl in vertical direction:
*** Set the Visible Property of pnlContent. This should collapse/expand the Collapsible Panel because of its AutoSize settings.
** When collapsing/expanding the UserControl in horizontal direction:
*** when collapsing
**** store the current Width of the Collapsible Panel UserControl in a Field prior to reducing the Width of the Collapsible Panel programmatically.
***** the Width to reduce it to depends on the VisualStyle selected
*** when expanding
**** restore the Width of the Collapsible Panel UserControl to the value you saved before in the Field
 
* Add ability to have the Collapsible Panel disabled [REF].
** Should be set from 'setter' of ''overriden'' Property 'Enabled'. ('Enabled' is a standard Property of the Control Class, therefore it needs to be overriden in this Class.)
** Needs to throw a custom Exception in case the Collapsible Panel is expanded to tell the caller that this is only supported when collapsed. This is to prevent frustrated users who would not be able to collapse a panel that appears to be collapsible if disabling would work when it is expanded.
** The title text should be displayed using a dark gray colour and all ways of collapsing/expanding need to be suppressed. If there is an Icon, it needs to be shown in gray-scale colours rather than full colour (ask ChristianK about how to do this).
 
* Add ability to hide a Collapsible Panel [REF].
** Implement two public Methods, Show() and Hide(). They would just toggle the Visible property of the UserControl.
*** The two Methods may be called independent of its collapsed/expanded state (unlike 'Enabled=false')
** The Form or UserControl which hosts a Collapsible Panel can also just set <code>MyCollapsiblePanel.Visible = true</code> or <code>MyCollapsiblePanel.Visible = false</code>. The two Methods just make it more obvious how to show or hide a CollapsiblePanel.
 
* Vertical collapsing mode only: Ability to display a 'x' (close) Button [REF].
** Add bool Property 'DisplayCloseButton'.
*** Show/hide the 'x' button in the 'setter' of the Property.
*** The 'x' button needs to be placed on the right side of the Title Panel, no matter whether the panel collapses to the right or to the left.
** On clicking the 'x' Button: raise a new custom Event 'CollapsiblePanelCloseButtonClicked' with no special arguments.
** Note: This is an ''optional'' feature.
* Test and demonstrate the new functionality in the test application.


===Step 4===
===Step 4===
* Collapsing in horizontal direction - EXTENDED [REF]
** Add a public enum to the .cs file in which the TPnlCollapsible Class is found (=the file you are working with), outside the definition of the TPnlCollapsible Class.
** Name it 'THorizontalCollapseDirection'.
*** Add the following values: hcdToTheLeft, hcdToTheRight.
** Add a Property 'HorizontalCollapseDirection' of Type 'THorizontalCollapseDirection'.
*** In the 'setter' of this Property set a Field of the Collapsible Panel class to the value that is passed in.
** Implement Panel which shows the Title Text rotated (90 degrees/180 degrees) when the Collapsible Panel is collapsed
*** Add a 'Ict.Common.Controls.TPnlGradient' named 'pnlHorizonalCollapsed' to the Content Panel. Make it as wide as the Collapsible Panel when it is collapsed and as high as the Content Panel. Set its gradient colours according to the values from the TVisualStyles instance that is currently used.
*** WinForms Labels cannot be rotated, but we need a rotated Label!
**** To get around that problem copy source code from the following web page: [http://stackoverflow.com/questions/416897/how-do-i-rotate-a-label-in-c]. This is code from a CodeProject project which has no license attached (ChristianK checked!), so we can use it in openPetra.
**** Create a new Control in the Ict.Common.Controls Project named 'lblOrientated.cs' and paste the copied source code there. Rename the Class to 'TLblOriented' and copy our usual file header into the cs file. Replace the author information with the name of the author and put a link to the Code Project page in the file header comment as well.
**** Create an instance of TLblOriented and add it to 'pnlHorizonalCollapsed', setting its 'Dock' property to 'DockStyle.Fill' (which is making it as high and as wide as 'pnlHorizonalCollapsed'). Set the 'TextOrientation' Property of the TLblOriented instance to 'Rotate'. Set the 'ContentAlignment' Property to 'MiddleCenter'.
**** If the value of the Field that holds the value of the HorizontalCollapseDirection is hcdToTheLeft, set the 'RotationAngle' Property of the TLblOriented instance to 90, otherwise to 180 (=degrees).
**** Set the Font and Font Size so that it looks as in the screenshots 'Horizontal: To-Do Bar - collapsed'.
**** Ensure that the rotated text is centered horizontally and vertically inside 'pnlHorizonalCollapsed'. If it isn't by default, change the code of TLblOriented to do that (prefereably doing that only if the value of the Control's 'ContentAlignment' Property is 'MiddleCenter').
** Add ability to limit the height of the internal Panel which shows rotated Title text to a certain number of pixels so that part of the hosted content is still visible [REF]
*** Add a Property 'RotatedTitleHeight' of Type 'int'.
**** In the 'setter' of this Property set the Height of 'pnlHorizonalCollapsed' to the value of the Property.
**** In doing so, the instance of TLblOriented should resize its Height accodingly as it is 'Docked', and the text shown in that Label should be re-centered automatically.
** Add Panel which can contain an arbitrary Control (which also can be a UserControl) [REF]
*** TODO
* Implement navigation by keyboard between the content hosted in the Content Panel (Task List or arbitrary UserControl) and the Title Panel [REF]
** Implement 'Highlighting' of Title Text if the Focus is there [REF]
* Implement handling of <ENTER> and <SPACE> keys for changing the collapsed/expanded state if the Focus is on the Title Text [REF]
* Implement Title Text shortcut key handling for <ALT>+<{underlined character}> (created by an ampersand & sign in the Title Text) [REF]
* Test and demonstrate the new functionality in the test application.
===Step 5===
* Add .NET Attributes to Properties, public Methods and to the Events for use in the WinForms Designer.
* Add .NET Attributes to Properties, public Methods and to the Events for use in the WinForms Designer.
* Test and demonstrate the UserControl in the WinForms Designer.
* Test and demonstrate the UserControl in the WinForms Designer.
* Add XML Documentation to  
* Add XML Documentation to  
** the Class
** the Class;
** the Properties
** the Properties;
** public and private Methods
** public and private Methods;
** the Enum
** the Enum;
** the Events
** the Events.
** The easiest way to add XML Documentation is to use SharpDevelop and do the following:
*** Place cursor in empty line above a Class, Property, Method, Enum, Event. Position the cursor on the same indentation level as the code for the Class, Property, Method, Enum, Event in the line below.
*** Enter ' <code>///</code> ' (triple forward slash)
*** SharpDevelop will have interted a XML Documentation template for you to fill in! :-)
* Check conformance with the openPETRA Code Style Guide!
* Check conformance with the openPETRA Code Style Guide!


==Approval of Functionality and Program Code==
==Approval of Functionality and Program Code==
Line 128: Line 273:
*** in combination with the 'Task List' (no matter what stage of completion that UserControl is, if it is past 'Step 1' this should be fine).
*** in combination with the 'Task List' (no matter what stage of completion that UserControl is, if it is past 'Step 1' this should be fine).
*** in combination with an arbitrary UserControl
*** in combination with an arbitrary UserControl
** show that the Collapsible Panel UserControl works on the 'Large Fonts (120 DPI)' display setting
* One ''special point'' will be awarded if the Collapsing Panel can be demonstrated inside openPETRA!  
* One ''special point'' will be awarded if the Collapsing Panel can be demonstrated inside openPETRA!  
** ChristianK will help with that
** ChristianK will help with that
* An additional ''special point'' will be awarded if the Collapsing Panel UserControl is integrated into the WinForms Generator!
* An additional ''special point'' will be awarded if the Collapsing Panel UserControl is integrated into the WinForms Generator!
** ChristianK will help with that
** ChristianK will help with that
* A ''special point'' will be awarded if the Collapsible Panel UserControl works well on either Linux and Mac OS X!

Latest revision as of 14:42, 19 August 2011

Introduction

There are three different styles in which a 'Collapsible Panel' should be able to be displayed in openPETRA when collapsing vertically and two different styles when collapsing horizontally (see screenshots on the side).

Combined: One vsHorizontalCollapse-Style Collapsible Panel (as 'Navigation Panel' in openPETRA Main Menu) hosting several vsAccordionPanel-Style Collapsible Panels
Combined: One vsHorizontalCollapse-Style Collapsible Panel (as 'Navigation Panel' in openPETRA Main Menu) hosting several vsAccordionPanel-Style Collapsible Panels - topmost vsAccordionPanel-Style Collapsible Panel collapsed
Vertical: Several vsTaskPanel-Style Collapsible Panels
Vertical: Several vsTaskPanel-Style Collapsible Panels - topmost vsTaskPanel-Style Collapsible Panel collapsed
Vertical: Task Panel, WinXP Explorer style (this is the 'Visual Style' we roughly want to mimic with vsTaskPanel, not the 'orangey' one above)


Vertical: A vsDashboard-Style Collapsible Panel (as 'Dashboard' in openPETRA Main Menu Task Area, hosting a UserControl)
Vertical: A vsDashboard-Style Collapsible Panel (as 'Dashboard' in openPETRA Main Menu Task Area, hosting a UserControl) - collapsed
Horizontal: A vsHorizontalCollapse-Style Collapsible Panel (as 'To-Do Bar' in openPETRA Main Menu Task Area)
Horizontal: A vsHorizontalCollapse-Style Collapsible Panel (as 'To-Do Bar' in openPETRA Main Menu Task Area) - collapsed
Horizontal: A vsHorizontalCollapse-Style Collapsible Panel (as 'Navigation Panel' in openPETRA Main Menu) - collapsed
Horizontal: A vsShepherd-Style Collapsible Panel (inside an openPETRA Shepherd [no collapse button shown here, though!])


With 'Collapsible Panel' we mean each of the panels that host either a 'Task List' (holding several Task Items), or any UserControl to be able to show custom content.

The main feature of a Collapsible Panel is that it can be expanded or collapsed - either Top, Bottom, Left, or Right depending on what the ".Dock" property is set to.

  • Top Collapsing (see first five screenshots on the side)
    • In the collapsed state only the Title Panel (a small panel containing a title text and a Button for expanding it and an optional Icon) is left. In this state the Collapsible Panel does not take up much space on the screen.
    • In the expanded state the Title Panel remains and in addition to that the actual content of the Collapsible Panel (a Task List or a UserControl) is shown. In this state the Collapsible Panel takes up at least as much space on the screen as its contents plus the space the Title Panel needs.
    • Note, that technically it does not expand to "at least as much space on the screen as its contents". Rather, it expands to the defined size of the panel, which presumably was set correctly by the user of the panel. This is also true for all following directions.
    • The button icons do not refresh correctly when collapsed/expanded. (see manual GUI tests).
  • Bottom Collapsing (see the next two screenshots on the side)
    • In the collapsed state only the Title Panel (a small panel containing a title text and a Button for expanding it and an optional Icon) is left. In this state the Collapsible Panel does not take up much space on the screen.
    • In the expanded state the Title Panel remains and in addition to that the actual content of the Collapsible Panel (a Task List or a UserControl) is shown. In this state the Collapsible Panel takes up at least as much space on the screen as its contents plus the space the Title Panel needs.
  • Right Collapsing (see next two screenshots on the side)
    • In the expanded state the Collapsible Panel is as wide as the content it hosts requires and as high as the content it hosts requires plus the space the Title Panel needs. The actual content of the Collapsible Panel (a Task List or a UserControl) is shown under the the Title Panel.
    • In the collapsed state the Collapsible Panel is just a narrow panel that doesn't show the content it hosts and is still as high as the content it hosts requires plus the space the Title Panel needs. In this state the Collapsible Panel does not take up much space on the screen. The Title Panel doesn't show the Title Text, but only a Button for expanding;
    • The Title Text is shown at a perpendicular angle underneath the Title Panel.
    • The button icons do not refresh correctly when collapsed/expanded. (see manual GUI tests).
    • Does the collapse icon need to appear on far left of Title when expanded??
  • Left Collapsing (see last two screenshots on the side)
    • In the expanded state the Collapsible Panel is as wide as the content it hosts requires and as high as the content it hosts requires plus the space the Title Panel needs. The actual content of the Collapsible Panel (a Task List or a UserControl) is shown under the the Title Panel.
    • In the collapsed state the Collapsible Panel is just a narrow panel that doesn't show the content it hosts and is still as high as the content it hosts requires plus the space the Title Panel needs. In this state the Collapsible Panel does not take up much space on the screen. The Title Panel doesn't show the Title Text, but only a Button for expanding;
    • The Title Text is shown at a perpendicular angle underneath the Title Panel.


The other features of a Collapsible Panel are

  • it supports different 'Styles', as shown in the screenshots along the side;
  • it can host either a 'Task List' or an arbitrary UserControl as a content;
  • it auto-sizes in both vertical and horizontal direction to always fit the size of the content.


There is another Project, 'Creation of a UserControl: Task List', whose UserControl is specifically designed to be hosted inside a Collapsible Panel.

Notes:

  • The corresponding Bug (=Feature Request) is Bug #205.
  • The Bazaar Branch in which the development is to happen is called 'dev_0000205_studentsJ2011_usercontrol_collapsiblepanel'.

Desired Outcome

  • Creation of one UserControl which acts as a 'Collapsible Panel' whose 'look and feel' can be set to five different styles, as shown in the screenshots along the side.
    • The different styles will need to affect
      • the Title Panel
        • font and colour of the Title Text
        • gradient colours of the Title Panel (compare screenshots 'Inside the Accordion Panel' and 'Inside a Task Panel' along the side)
        • height of the Title Panel (so it accommodates different Font sizes)
        • two Icons for collapsing/expanding on the Title Button
          • there are two sets containing four Icons each: one set for vertical collapsing (up-down arrows) and one set for horizontal collapsing (left-right arrows) mode. (Each set contains two Icons plus two 'hover' Icons, making four Icons.)
      • the Content Panel
        • gradient colours of the Content Panel (which hosts the actual content, e.g. Task List or a UserControl) (see screenshot 'Inside the Accordion Panel' along the side)
  • Expand/Collapse
    • The UserContol needs to collapse when the collapse/expand Button is clicked and it is currently expanded, and it needs to expand when the collapse/expand Button is clicked and it is currently collapsed.
    • Vertical collapsing mode only: It shall also toggle its collapsed/expanded state if the Title Panel, the Title Text or the Title Icon is clicked.
    • The Icon on the Title Button needs to change on toggling to show the correct Icon for the collapsed/expanded state. This almost works. See the above instructions about "main funcitonality" (the bullets not not crossed out).
  • The UserControl needs to support collapsing in either horizontal or vertical direction.
    • When set up to collapse in horizontal direction
      • there needs to be an option to specify whether it collapses 'to the right' or 'to the left'.
      • ... This will affect the horizontal position of the collapse/expand Button, which Icon is shown for collapsing/expanding and whether the Title Text is rotated 90 degrees or 180 degrees (compare screenshots 'Horizontal: To-Do Bar - collapsed' and 'Horizontal: Accordion Panel - collapsed').
      • a Panel which can contain an arbitrary Control (which also can be a UserControl) needs to be shown on request and display the desired Control (Icon and text 'No Reminders.' in screenshot 'Horizontal: To-Do Bar - collapsed').
      • it must be possible to limit the height of the internal Panel which shows rotated Title text to a certain number of pixels so that part of the hosted content is still visible (Icons for openPetra Modules in screenshot 'Horizontal: Accordion Panel - collapsed'). If its height isn't limited, this internal Panel shall fill the full height of the UserControl in order to hide the hosted content completely.
  • Dealing with hosted content
    • When the UserControl is hosting the 'Task List', it needs to accept the Task Items as a single XmlNode and pass it on to the Task List.
    • When the UserControl is hosting an arbitrary UserControl, it needs to accept information about it (the Namespace it is found in and its Class name) so it can instantiate it.
    • The UserControl needs to dynamically create the hosted content (a Task List or an arbitrary UserControl) the first time it is expanded.
      • This is in order to speed up the realisation (painting) of a screen that hosts a Collapsing Panel which is in its 'collapsed' state (only the Title Panel needs to be realised in this case!).
  • The UserControl needs to be able to auto-size itself in vertical and horizontal direction - depending on the size needed for hosting the Task List or a UserControl in the Content Panel. ~ I (sethb) did not explicitly test this in manual GUI tests.
  • The UserControl needs to have a read-only Property 'IsCollapsed'. (This can be used by the screen which hosts this UserControl to inquire its state.)
  • The UserControl needs to have Properties to set the Title Text
  • The UserControl needs to have Properties to set the optional Title Icon.
  • The UserControl needs to raise Events when it got Expanded or Collapsed.
    • On receiving those Events, the screen which hosts this UserControl can do any necessary screen re-arrangement, or change the tick on a MenuItem, for example.
  • Navigation between the content hosted in the Content Panel (Task List or arbitrary UserControl) and the Title Panel needs to be possible by keyboard!
    • <CURSOR-UP> and <CURSOR-DOWN> keys for navigation
      • 'Highlighting' of Title Text if the Focus is there
        • Highlighting should be done by painting a rectangle with dotted line around the Title Text
    • <ENTER> and <SPACE> keys for changing the collapsed/expanded state if the Focus is on the Title Text
  • Title Text will need to be able to show an underlined character (designated by an ampersand & sign in the text). If the user presses <ALT>+<{underlined character}>, the collapsed state shall be changed to expanded (only if the UserControl is currently collapsed) and the input Focus shall be given to the Content Panel.
    • See screenshot 'Menu Items in Accordion Panel' along the side (&General Ledger Collapsible Panel)
  • Disabling of a Collapsible Panel must be possible, but only if it is in its 'collapsed' state.
  • Hiding of a Collapsible Panel must be possible, independent of its collapsed/expanded state.
  • Public Methods for Disabling/Enabling and Hiding/Showing of a Collapsible Panel must be implemented.
    • Method for Disabling needs to throw a custom Exception if it is called while the Collapsible Panel is expanded.
  • The UserControl needs to work with the 'Large Fonts (120 DPI)' display setting.
    • If you can get it to work with any arbitrary DPI setting this would be good, but this isn't a requirement.
  • The UserControl should work on Linux and Mac OS X, if possible (this isn't a requirement).
    • Don't spend too much time on this - if you can get it to work without too much effort then do it, otherwise just write down the problems you experience so we can follow it up in time.
    • Test this only once a while during development - testing this shouldn't consume much time.
  • OPTIONAL: Vertical collapsing mode only: Ability to display a 'x' button which would raise a custom Event. The screen or control which hosts the Collapsible Panel would make the Collapsible Panel invisible on receiving this Event (see screenshots for 'Task Panel' and 'To-Do Bar').
  • Cooperating with the design view.
    • In order for the Design view to be useful for programmers to use, the panel must cooperate with the design view mode. Therefore, it must be visible in design view. More specifically, if that is too cumbersome, as long as some placeholder is there in design view so that the positioning of other elements works that could work too, but you will need specific approval by Lead Developer to make sure that the nuances are correct.

Outline of the Solution

This lists the basic steps for getting to the desired outcome.

Where references are made to items which are described in the 'Desired Outcome' section, '[REF]' will be mentioned.

Step 1

Important: Follow the openPETRA 'Coding Standard and Guidelines' for all code that you write!

  • Start with an existing UserControl
    • Open the Ict.Common.Controls C# Project (located in \csharp\ICT\Common\Controls) and open the Class 'TPnlCollapsible' contained in file 'pnlCollapsible.cs'.
    • This is a basic implementation of a 'Collapsible Panel' which collapses only in vertical direction.
      • Have a good look how things are done and what is already implemented.
      • You can play around with that Panel by starting openPetra and clicking 'Find Partners' in the Task List on the right.
        • You won't be able to find any Partners at the moment as this is an empty openPETRA database, but the Collapsible Panel still works.
          • Note that the Panel can be expanded/collapsed by clicking its expand/collapse icon [REF], by clicking anything else in the Title Panel [REF], and by clicking the 'Partner Info' ToolBarButton and by checking/unchecking the 'View'->'Partner Info Panel' MenuItem.
  • Extend the UserControl so that it can also expand and collapse in horizontal direction - BASIC [REF]
    • Add a public enum to that file, outside the definition of the TPnlCollapsible Class.
      • Name it 'TCollapseDirection'.
      • Add the following values: cdVertical, cdHorizontal
    • Add a 'CollapseDirection' Property of Type 'TCollapseDirection'.
      • Implement the change of collapsing behaviour in a private Method that gets called from the 'setter' of this Property.
        • The set of four Icons with arrows for collapsing/expanding need to be swapped with the other set of four icons [REF]
          • For this, four new Icons need to be added to the ImageList 'imlUpDownArrows'. To do this, switch to the Designer View of the IDE and select the 'imlUpDownArrows' Control in the area on the bottom. Then click on the '...' button in the Properties Panel to edit the ImageList collection of Icons. Add four new Icons for the horizontal collapse mode (ask ChristianK for the icon files).
        • Show/hide the Title Text in the Title Panel.
    • The existing UserControl has hard-coded values for collapsed and expanded height (COLLAPSEDHEIGHT and EXPANDEDHEIGHT). For the moment we will use those for setting the collapsed and expanded width as well. This will be improved on in Step 2.
  • Test and demonstrate this in a small test application, which you should create for that purpose.
    • The Test Application is to be created in the directory \csharp\ICT\Testing\Common\Controls (doesn't exist yet) and to be called 'ControlTestBench.sln'.
    • It should have a main Form with some Buttons. Each of the Buttons should launch a test Form that is specific for a certain UserControl.
    • Co-ordintate yourself with the creators of the 'Task List' to ensure that only one of you creates that application - namely the one who gets to this step first.

Step 2

  • Add a public enum to the .cs file in which the TPnlCollapsible Class is found (=the file you are working with), outside the definition of the TPnlCollapsible Class.
    • Name it 'THostedControlKind'.
    • Add the following values: hckUserControl, hckTaskList
  • Add a 'HostedControlKind' Property of Type 'THostedControlKind'.
    • In the 'setter' of this Property set a Field of the Collapsible Panel class to the value that is passed in.
  • Add ability to instantiate and host an arbitrary UserControl [REF]
    • The current implementation simply exposes the 'pnlContent' Control so an inheritor can 'add' an arbitrary Control in it. Make 'pnlContent' Control private again (see also XML comment on pnlContent in the pnlContent.Designer.cs file).
    • pnlContent should not need to be inherited from anymore to place arbitrary Controls on its Content Panel. Instead, pnlContent will need to get the ability to instantiate and host an arbitrary UserControl. This makes hosting a Collapsible Panel easier, is more flexible, and allows to encapsulate the logic for postponing the instantiation of the hosted UserControl until the point in time when the Collapsible Panel is actually expanded, therefore speeding up the realisation (painting) of a Form that hosts a collapsed Collapible Panel.
      • Add Properties 'UserControlNamespace' and 'UserControlClass', both of Type 'string'. They will need to be set by the Form or Control which hosts the Collapsible Panel. [REF]
        • In the 'setter' of both these Properties throw a custom Exception (which you shall specify in the same .cs file, but outside the definition of the TPnlCollapsible Class) if the 'HostedControlKind' Property is set to hckTaskList. This will tell the caller that the Control is set to host a Task List and therefore can't host a UserControl at the same time.
      • Add read-only Property 'UserControlInstance' of Type 'UserControl'. This will return null if the UserControl wasn't instantiated yet, and will return the actual instance of the dynamically created UserControl once it has been instantiated. (This instance can be casted to a specific Type by the Form or Control which hosts the Collapsible Panel and it can then call Methods or pass in values into Properties of that UserControl and receive Events from it.)
      • Add public Method 'RealiseUserControlNow()' to force the Collapsible Panel to create an instance of the UserControl when called (needed only in case the Form or Control which hosts the Collapsible Panel wants to create the instance while the Collapsible Panel is still closed. The Form or Control which hosts the Collapsible Panel might want to do this in a background thread to populate the UserControl [which might well load data from the DB] while the user isn't aware of it and so that it expands promptly once the user expands the Collapsible Panel).
      • Add private Method 'RealiseUserControl()'. It needs to be called from the public Method 'RealiseUserControlNow' and once the Collapsible Panel gets expanded for the first time.
        • The first thing this Method needs to do is to check whether it has all the necessary information. Inspect the values of both the 'UserControlNamespace' and 'UserControlClass' Properties and check wheter they aren't String.Empty. Should one of them be String.Empty throw a System.ArgumentException, specifying the reason for it in it's String Argument.
        • This Method will utilise a .NET technique called 'Reflection' to load an Assembly (=DLL) which contains the Namespace specified with Property 'UserControlNamespace' and to then create an instance of the Class which is specified with Property 'UserControlClass'.
          • .NET Reflection is tricky! You can find code that does something similar, although more complicated, in Method ExecuteAction in Class Ict.Common.Controls.TLstTask (found in \csharp\Ict\Common\Controls\lstTask.cs). (TLstTask is the Control on the right side of the openPETRA Main Menu that dynamically loads DLLs, instantiates openPETRA screen Classes and in the end shows openPETRA screens once the user clicks on a list item.)
            • The key commands in that Method are 'Assembly.LoadFrom' and 'Activator.CreateInstance'. Search for them in the Method and see how they are used. TLstTask caches Assemblies for re-use, you don't need to do that in this UserControl.
            • Try to write code that loads the correct assembly and instantiates the specified UserControl. You might want to 'google' for '.NET Reflection', 'Assembly.LoadFrom' and 'Activator.CreateInstance' to see how others are using them. If you get stuck, get ChristianK to help you - you shouldn't spend too much time on that basic, although very important, feature of the Collapsible Panel.
            • Cast the created instance to Type UserControl and hold it in a Field (of Type UserControl) of the TPnlCollapsible Class.
  • Add ability to instantiate and host a 'Task List' [REF]
    • Check with the creators of the Task List UserControl whether they are already past 'Step 1'. This would be a requirement for you to use it with the Collapsible Panel.
      • If it is past 'Step 1' then creators of the Task List should make a Commit to their Branch so you can merge it into your branch and use it with the Collapsible Panel.
      • If it isn't past 'Step 1' yet you can still add the Property 'TaskListNode' (see below) but you can't instantiate the Task List on expanding the Collapsible Panel (obviously). Check back with them regularly to see whether they are past 'Step 1'.
    • Add Property 'TaskListNode' Property of type XmlNode. [REF]
      • In the 'setter' of this Property set a Field of the Collapsible Panel class to the value that is passed in, not the 'XmlNode' Property of the Task List instance, as that instance might not exist yet if the Collapsible Panel is collapsed when this Property is written to!
      • Throw a custom Exception (which you shall specify in the same .cs file, but outside the definition of the TPnlCollapsible Class) if the 'HostedControlKind' Property is set to hckUserControl. This will tell the caller that the Control is set to host a UserControl and therefore can't host a Task List at the same time.
    • Add read-only Property 'TaskListInstance' of Type 'TTaskList'. This will return null if the Task List wasn't instantiated yet, and will return the actual instance of the dynamically created Task List once it has been instantiated. (This instance can be used by the Form or Control which hosts the Collapsible Panel to call Methods of that Task List instance, to set its Properties and to receive Events from it.)
  • Dynamically create the hosted content (a Task List or an arbitrary UserControl) the first time the Collapsible Panel is expanded [REF]
    • This will need to happen in the public Method 'Expand' which already exists in a very basic form.
    • Add a 'switch' block in this Method which switches on the value of the 'HostedControlKind' Property and calls one of the following two new private Methods: InstantiateUserControl(), InstantiateTaskList().
      • The InstantiateUserControl Method simply needs to call the private Method 'RealiseUserControl()'.
      • The InstantiateTaskList Method will need to create an instance of Class 'TTaskList', set its 'TaskListNode' Property and hold it in a Field (of Type TTaskList) of the TPnlCollapsible Class.
  • Test and demonstrate the new functionality in the test application.

Step 3

  • Add a Property 'Title Icon' of Type 'Image' to be able to show an optional Title Icon in the Title Panel [REF].
    • In the 'setter':
      • If a non-null value is passed in, move the lblDetailHeading Control about 20 pixels to the right, add the Icon to pnlTitleText and set the Icon' Location.X value to the lblDetailHeading's Location.X original value.
      • If a null value is passed in, place the lblDetailHeading Control at its original location and hide the Icon (if it was ever instantiated in the first place).
  • Add a 'VisualStyle' Property of Type 'TVisualStyles'.
    • Note: The 'TVisualStyles' Class was created as part of Project 'Task List'. Merge code in from that Project's branch to get this Class.
    • All five Visual Styles will be used by the Collapsible Panel UserControl.
  • Implement the change of visual style in a private Method that gets called from the 'setter' of this Property.
    • Restrict the choice of Visual Style as follows:
      • vsAccordionPanel, vsTaskPanel and vsDashboard can be used only if the Collapsible Panels collapses vertical.
      • vsHorizontalCollapse and vsShepherd can be used only if the Collapsible Panels collapses horizontal (see 'Horizontal: To-Do Bar' and 'Horizontal: Accordion Panel' screenshots).
      • Throw a custom Exception if the user tries to set a Visual Style that doesn't go with the TCollapseDirection value.
    • Change of visual style needs to affect various things (e.g. font, title panel height, background, ...). See [REF] and screenshots along the side.
    • Use UserControl 'Ict.Common.Controls.TPnlGradient' instead of a standard WinForms Panel for the Title Panel (pnlTitleText) to have a panel that supports a gradient background (see pnlContent which alread is a TPnlGradient).
  • Add ability to auto-size itself in vertical and horizontal direction [REF].
    • The UserControl already has the properties 'AutoSize' and 'AutoSizeMode' set correctly, so the basic .NET WinForm requirements for that ability should already be met (needs to be verified, though).
    • When collapsing/expanding the UserControl in vertical direction:
      • Set the Visible Property of pnlContent. This should collapse/expand the Collapsible Panel because of its AutoSize settings.
    • When collapsing/expanding the UserControl in horizontal direction:
      • when collapsing
        • store the current Width of the Collapsible Panel UserControl in a Field prior to reducing the Width of the Collapsible Panel programmatically.
          • the Width to reduce it to depends on the VisualStyle selected
      • when expanding
        • restore the Width of the Collapsible Panel UserControl to the value you saved before in the Field
  • Add ability to have the Collapsible Panel disabled [REF].
    • Should be set from 'setter' of overriden Property 'Enabled'. ('Enabled' is a standard Property of the Control Class, therefore it needs to be overriden in this Class.)
    • Needs to throw a custom Exception in case the Collapsible Panel is expanded to tell the caller that this is only supported when collapsed. This is to prevent frustrated users who would not be able to collapse a panel that appears to be collapsible if disabling would work when it is expanded.
    • The title text should be displayed using a dark gray colour and all ways of collapsing/expanding need to be suppressed. If there is an Icon, it needs to be shown in gray-scale colours rather than full colour (ask ChristianK about how to do this).
  • Add ability to hide a Collapsible Panel [REF].
    • Implement two public Methods, Show() and Hide(). They would just toggle the Visible property of the UserControl.
      • The two Methods may be called independent of its collapsed/expanded state (unlike 'Enabled=false')
    • The Form or UserControl which hosts a Collapsible Panel can also just set MyCollapsiblePanel.Visible = true or MyCollapsiblePanel.Visible = false. The two Methods just make it more obvious how to show or hide a CollapsiblePanel.
  • Vertical collapsing mode only: Ability to display a 'x' (close) Button [REF].
    • Add bool Property 'DisplayCloseButton'.
      • Show/hide the 'x' button in the 'setter' of the Property.
      • The 'x' button needs to be placed on the right side of the Title Panel, no matter whether the panel collapses to the right or to the left.
    • On clicking the 'x' Button: raise a new custom Event 'CollapsiblePanelCloseButtonClicked' with no special arguments.
    • Note: This is an optional feature.
  • Test and demonstrate the new functionality in the test application.

Step 4

  • Collapsing in horizontal direction - EXTENDED [REF]
    • Add a public enum to the .cs file in which the TPnlCollapsible Class is found (=the file you are working with), outside the definition of the TPnlCollapsible Class.
    • Name it 'THorizontalCollapseDirection'.
      • Add the following values: hcdToTheLeft, hcdToTheRight.
    • Add a Property 'HorizontalCollapseDirection' of Type 'THorizontalCollapseDirection'.
      • In the 'setter' of this Property set a Field of the Collapsible Panel class to the value that is passed in.
    • Implement Panel which shows the Title Text rotated (90 degrees/180 degrees) when the Collapsible Panel is collapsed
      • Add a 'Ict.Common.Controls.TPnlGradient' named 'pnlHorizonalCollapsed' to the Content Panel. Make it as wide as the Collapsible Panel when it is collapsed and as high as the Content Panel. Set its gradient colours according to the values from the TVisualStyles instance that is currently used.
      • WinForms Labels cannot be rotated, but we need a rotated Label!
        • To get around that problem copy source code from the following web page: [1]. This is code from a CodeProject project which has no license attached (ChristianK checked!), so we can use it in openPetra.
        • Create a new Control in the Ict.Common.Controls Project named 'lblOrientated.cs' and paste the copied source code there. Rename the Class to 'TLblOriented' and copy our usual file header into the cs file. Replace the author information with the name of the author and put a link to the Code Project page in the file header comment as well.
        • Create an instance of TLblOriented and add it to 'pnlHorizonalCollapsed', setting its 'Dock' property to 'DockStyle.Fill' (which is making it as high and as wide as 'pnlHorizonalCollapsed'). Set the 'TextOrientation' Property of the TLblOriented instance to 'Rotate'. Set the 'ContentAlignment' Property to 'MiddleCenter'.
        • If the value of the Field that holds the value of the HorizontalCollapseDirection is hcdToTheLeft, set the 'RotationAngle' Property of the TLblOriented instance to 90, otherwise to 180 (=degrees).
        • Set the Font and Font Size so that it looks as in the screenshots 'Horizontal: To-Do Bar - collapsed'.
        • Ensure that the rotated text is centered horizontally and vertically inside 'pnlHorizonalCollapsed'. If it isn't by default, change the code of TLblOriented to do that (prefereably doing that only if the value of the Control's 'ContentAlignment' Property is 'MiddleCenter').
    • Add ability to limit the height of the internal Panel which shows rotated Title text to a certain number of pixels so that part of the hosted content is still visible [REF]
      • Add a Property 'RotatedTitleHeight' of Type 'int'.
        • In the 'setter' of this Property set the Height of 'pnlHorizonalCollapsed' to the value of the Property.
        • In doing so, the instance of TLblOriented should resize its Height accodingly as it is 'Docked', and the text shown in that Label should be re-centered automatically.
    • Add Panel which can contain an arbitrary Control (which also can be a UserControl) [REF]
      • TODO
  • Implement navigation by keyboard between the content hosted in the Content Panel (Task List or arbitrary UserControl) and the Title Panel [REF]
    • Implement 'Highlighting' of Title Text if the Focus is there [REF]
  • Implement handling of <ENTER> and <SPACE> keys for changing the collapsed/expanded state if the Focus is on the Title Text [REF]
  • Implement Title Text shortcut key handling for <ALT>+<{underlined character}> (created by an ampersand & sign in the Title Text) [REF]
  • Test and demonstrate the new functionality in the test application.

Step 5

  • Add .NET Attributes to Properties, public Methods and to the Events for use in the WinForms Designer.
  • Test and demonstrate the UserControl in the WinForms Designer.
  • Add XML Documentation to
    • the Class;
    • the Properties;
    • public and private Methods;
    • the Enum;
    • the Events.
    • The easiest way to add XML Documentation is to use SharpDevelop and do the following:
      • Place cursor in empty line above a Class, Property, Method, Enum, Event. Position the cursor on the same indentation level as the code for the Class, Property, Method, Enum, Event in the line below.
      • Enter ' /// ' (triple forward slash)
      • SharpDevelop will have interted a XML Documentation template for you to fill in! :-)
  • Check conformance with the openPETRA Code Style Guide!

Approval of Functionality and Program Code

  • Have both the functionality and the program code reviewed by ChristianK and Prof. Nurkkala.
  • Show the UserControl in the WinForms Designer. Documentation of Properties, Events and the design-time experience will be evaluated by ChristianK and Prof. Nurkkala.
  • Demonstrate the Collapsing Panel in the test application
    • show several instances to demonstrate the auto-sizing capability
      • in combination with the 'Task List' (no matter what stage of completion that UserControl is, if it is past 'Step 1' this should be fine).
      • in combination with an arbitrary UserControl
    • show that the Collapsible Panel UserControl works on the 'Large Fonts (120 DPI)' display setting
  • One special point will be awarded if the Collapsing Panel can be demonstrated inside openPETRA!
    • ChristianK will help with that
  • An additional special point will be awarded if the Collapsing Panel UserControl is integrated into the WinForms Generator!
    • ChristianK will help with that
  • A special point will be awarded if the Collapsible Panel UserControl works well on either Linux and Mac OS X!