WorldWind的界面有一个工具栏和层管理器,这些界面元素都是通过D3D绘制的。其中,WorldWindow有一个MenuBar对象,代表工具栏,工具栏包含两类按钮,一类是工具按钮m_toolsMenuButtons,包括LayerManagerButton,PositionMenuButton,LatLonMenuButton等,他们均继承自MenuButton类。另一类是图层按钮m_layersMenuButtons,用于控制图层的显示和隐藏,一般是LayerShortcutMenuButton。按钮类关系图如下:
MenuBar类
MenuBar类负责管理和显示工具栏,其类图如下:
成员变量:
//工具菜单按钮列表
protected ArrayList m_toolsMenuButtons = new ArrayList();
//图层菜单按钮列表
protected ArrayList m_layersMenuButtons = new ArrayList();
//工具栏可视状态
protected VisibleState _visibleState = VisibleState.Visible;
protected DateTime _lastVisibleChange = DateTime.Now;
protected float _outerPadding = 5; //按钮外围填充间隔
protected int x;
protected int y;
protected int hideTimeMilliseconds = 100;
protected MenuAnchor m_anchor = MenuAnchor.Left; //工具栏停靠位置
protected bool _isHideable; //工具栏是否可以隐藏
protected const float padRatio = 1/9.0f;
protected CursorType mouseCursor;
protected int chevronColor = Color.Black.ToArgb(); //图标上按钮按下标识V形图案颜色
protected CustomVertex.TransformedColored[] enabledChevron = new CustomVertex.TransformedColored[3]; //绘制V形图案的三个顶点
protected Sprite m_sprite; //用于二维绘图的sprite对象
以下函数用于添加、删除工具菜单按钮和图层菜单按钮。
public void AddToolsMenuButton(MenuButton button):
public void AddToolsMenuButton(MenuButton button, int index):
public void RemoveToolsMenuButton(MenuButton button):
public void AddLayersMenuButton(MenuButton button):
public void AddLayersMenuButton(MenuButton button, int index):
public void RemoveLayersMenuButton(MenuButton button):
int _curSelection = -1; //当前选中的按钮ID
处理鼠标事件:
public bool OnMouseUp(MouseEventArgs e):如果选择了按钮,反选按钮状态。否则,将鼠标释放事件逐个传递给按下状态的工具菜单按钮处理。
public bool OnMouseDown(MouseEventArgs e):将鼠标按下事件传递给工具菜单按钮处理。
public bool OnMouseMove(MouseEventArgs e):先将鼠标移动事件传递给工具菜单按钮处理。然后根据鼠标移动位置计算选择的按钮。工具栏可以停靠在顶部、底部和右部,但是绘图的操作都是按照停靠在顶部计算的,停靠其他地方,计算有点问题。
public bool OnMouseWheel(MouseEventArgs e):将鼠标滚轮事件传递给工具菜单按钮处理。
渲染工具栏:
public void Render(DrawArgs drawArgs):首先调用工具按钮的Render函数,渲染按钮对应的功能项,如层管理器按钮会调用它包含的LayerManagerMenu对象的Render函数绘制层管理器。然后调用工具按钮和图层按钮的update函数更新状态。根据工具栏停靠位置计算xy的起始位置,调用MenuUtil的DrawBox函数绘制工具栏的底框(4个顶点,TriangleStrip类型)。然后绘制按钮,使用ImageHelper.LoadIconTexture加载图片纹理,绘制按下按钮的三角形(3个顶点,TriangleList类型),最后调用按钮的RenderEnabledIcon渲染按钮图标。
MenuButton类
成员变量:
private string _iconTexturePath; //按钮图片纹理路径
private Texture m_iconTexture; //图片对应纹理对象
private System.Drawing.Size _iconTextureSize; //纹理大小
string _description; //文字描述,选中状态绘制
float curSize; //当前大小
static int white = System.Drawing.Color.White.ToArgb();
static int black = System.Drawing.Color.Black.ToArgb();
static int transparent = Color.FromArgb(140,255,255,255).ToArgb();
int alpha; //颜色alpha值,会逐步变化
const int alphaStep = 30;
const float zoomSpeed = 1.2f;
public static float NormalSize; //未选中状态大小
public static float SelectedSize; //选中状态大小
public void InitializeTexture(Device device):使用ImageHelper.LoadIconTexture加载图片纹理,并记录纹理大小。
public void RenderEnabledIcon(Sprite sprite, DrawArgs drawArgs, float centerX, float topY,
bool selected ):
public void RenderLabel( DrawArgs drawArgs, int x, int y, int buttonHeight, bool selected ):
private void RenderIcon(Sprite sprite, float centerX, float centerY, int buttonWidth, int buttonHeight, int color, Texture t):
LatLonMenuButton经纬网菜单按钮类
成员变量:
World _parentWorld; //所属的球体
public override bool IsPushed(): 按钮是否处于按下状态。状态信息保存在地球设置的showLatLonLines参数中。
public override void SetPushed(bool isPushed):设置按钮的状态,修改地球设置的showLatLonLines参数。
PositionMenuButton类
public override bool IsPushed():按钮是否处于按下状态。状态信息保存在地球设置的showPosition参数中。
public override void SetPushed(bool isPushed):设置按钮的状态,修改地球设置的showPosition和showCrosshairs参数。
LayerShortcutMenuButton类
成员变量:
bool _isPushed = false; //是否处于按下状态
WorldWind.Renderable.RenderableObject _ro; //图层所在的可渲染对象
public override bool IsPushed():按钮是否处于按下状态。状态信息保存在_isPushed成员变量中。
public override void SetPushed(bool isPushed):设置按钮的状态,修改_isPushed值,如果图层对应的可渲染对象当前为隐藏状态,且它的父节点只显示一个图层,则将父节点的子节点全部隐藏(TurnOffAllChildren)。 设置可渲染对象的显隐状态。图层名称为Placenames和Boundaries,按下状态还要保存到地球设置的showPlacenames和showBoundaries参数中。
public override void Update(DrawArgs drawArgs):如果对应可渲染对象的显隐状态与按钮的状态不一致,根据显隐状态修改按钮的状态。
LayerManagerButton类
该类控制图层管理器的显示隐藏和绘制等。成员变量:
World _parentWorld; //球体对象
LayerManagerMenu lmm; //层管理器对话框对象
public override bool IsPushed():按钮是否处于按下状态。状态信息保存在地球设置的showLayerManager参数中。
public override void SetPushed(bool isPushed):设置按钮的状态,修改地球设置的showLayerManager参数。
public override bool OnMouseDown(MouseEventArgs e):
public override bool OnMouseMove(MouseEventArgs e):
public override bool OnMouseUp(MouseEventArgs e):
public override bool OnMouseWheel(MouseEventArgs e):鼠标事件,如果按钮处于按下状态,且图层管理器不为空,则将鼠标事件传递给图层管理器。
public override void Render(DrawArgs drawArgs):如果按钮处于按下状态,检查图层管理器是否为空,为空则创建该对象,调用层管理器的Render函数,绘制图层管理器。
图层管理器相关的类
SideBarMenu类
public long Id;
public readonly int Left;
public readonly int Top = 120;
public int Right = World.Settings.layerManagerWidth;
public int Bottom;
public readonly float HeightPercent = 0.9f;
private Vector2[] outlineVerts = new Vector2[5];
public void Render(DrawArgs drawArgs):
LayerManagerMenu类
public int DialogColor = System.Drawing.Color.Gray.ToArgb();
public int TextColor = System.Drawing.Color.White.ToArgb();
public LayerMenuItem MouseOverItem;
public int ScrollBarSize = 20;
public int ItemHeight = 20;
World _parentWorld;
MenuButton _parentButton;
bool showScrollbar;
int scrollBarPosition;
float scrollSmoothPosition; // Current position of scroll when smooth scrolling (scrollBarPosition=target)
int scrollGrabPositionY; // Location mouse grabbed scroll
bool isResizing;
bool isScrolling;
int leftBorder=2;
int rightBorder=1;
int topBorder=25;
int bottomBorder=1;
Microsoft.DirectX.Direct3D.Font headerFont;
Microsoft.DirectX.Direct3D.Font itemFont;
Microsoft.DirectX.Direct3D.Font wingdingsFont;
Microsoft.DirectX.Direct3D.Font worldwinddingsFont;
ArrayList _itemList = new ArrayList();
Microsoft.DirectX.Vector2[] scrollbarLine = new Vector2[2];
public ContextMenu ContextMenu;
WidgetMenuButton类
有两个相同名称的类,一个是根目录下WidgetMenuButton.cs的namespace WorldWind,似乎已不再使用。另一个在Widgets目录下WidgetMenuButton.cs文件中,namespace WorldWind.NewWidgets。两个文件的实现相似,只是成员变量一个是 WorldWind.Widgets.IWidget m_widget,一个是 WorldWind.NewWidgets.IWidget m_widget。