In the previous article, we set our goal. Where should we start from: remove the hateful if and switch statements, remove repeated statements, or reduce the number of rows of long methods? This is a problem. Perhaps the only thing that can be determined is not to touch the "8 pixel" limit.
After carefully analyzing the code, we will find that the main cause of the Code high repetition rate in this control is that if and switch are used in large batches. Further analysis: Why does the collapsiblesplitter brother use so many branch statements? This is the case... Hey, J:
- This control supports five painting styles (Mozilla, XP, Win9x, doubledots, and lines). The Code must determine which style the user selects;
- This control supports four dock modes (top, bottom, left, and right). The Code must determine which dock mode the user selects;
- The control changes back and forth in multiple States when drawing interfaces and controlling behaviors.
What does object-oriented language use to replace these branch statements? Put the problem into your mind and turn it into two circles-well, strategy and state ). Well, let's use these two modes for our deodorization work.
First, let's take a look at these two models (extracted from the design patterns mini manual ):
Strategy Mode
State Mode
First, we define the style series "policies ". Based on the direction (horizontal or vertical), the Code for drawing the interface style is also quite different. Therefore, we define two different painting functions for the base class, representing horizontal painting and vertical painting respectively. The following is a subclass of the abstract base class visualstyle and its Mozilla painting style:
namespace ISAK.WinGui.Controls.Styles
{
abstract class VisualStyle
{
public abstract void DrawVertical(Graphics g, int x, int y, Color lineColor);
public abstract void DrawHorizontal(Graphics g, int x, int y, Color lineColor);
}
class VisualStyleMozilla: VisualStyle
{
public override void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y + (i * 3), x + 1, y + 1 + (i * 3));
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
g.DrawLine(new Pen(lineColor), x + 2, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
}
}
public override void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x + (i * 3), y, x + 1 + (i * 3), y + 1);
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1 + (i * 3), y + 1, x + 2 + (i * 3), y + 2);
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
g.DrawLine(new Pen(lineColor), x + 1 + (i * 3), y + 2, x + 2 + (i * 3), y + 2);
}
}
}
}
Other subclasses of the painting style include visualstylexp, visualstylewin9x, visualstyledoubledots, and visualstylelines. Their code is also directly copied from the relevant positions in the onpaint method.
Next, we add a private member to the collapsiblesplitter class.
private Styles.VisualStyle styleDrawer;
Then, we modify the Set Method of the visualstyle attribute:>
public VisualStyles VisualStyle
{
get{ return this.visualStyle; }
set
{
this.visualStyle = value;
switch (value)
{
case VisualStyles.Mozilla:
styleDrawer = new Styles.VisualStyleMozilla();
break;
case VisualStyles.XP:
styleDrawer = new Styles.VisualStyleXP();
break;
case VisualStyles.Win9x:
styleDrawer = new Styles.VisualStyleWin9x();
break;
case VisualStyles.DoubleDots:
styleDrawer = new Styles.VisualStyleDoubleDots();
break;
case VisualStyles.Lines:
styleDrawer = new Styles.VisualStyleLines();
break;
}
this.Invalidate();
}
}
Remove the two switches in the onpaint method, and change the code of the switch series above to the following:
styleDrawer.DrawVertical(g, x, y, hot ? hotColor : BackColor);
The following code of the switch series is changed to>
styleDrawer.DrawHorizontal(g, x, y, hot ? hotColor : BackColor);
The bad smell of style painting is now done. Although there are still some unsatisfactory aspects (look at the two hot ones above? Hotcolor: backcolor. Hey, do you have some subtle work? Wait till the final time.