Xsconsole界面显示类的介绍

1. 概述

本文档主要介绍XSConsole的界面显示所使用的主要几个类,以及它们相互之间的关系。

2 XSConsole主界面介绍

Xsconsole主界面元素介绍,如下图所示。主界面可分为两部分,TopWindow(顶部)和MainWindow,这两个都是属于CursesWindow类。(后面介绍各个类以及之间的关系)MainWindow所占据的区域是整个下半部分,包含左侧的MenuPane和右侧的StatusPane,但实际上这一部分界面是有RootDialogue负责的。MenuPane是一个DialoguePane的对象,界面上主要包含有TitleField(显示Customize System),MenuField(菜单列表)和KeyHelpField(按键帮助信息)。StatusPane也是一个DialoguePane的对象,界面上包含TitleField(显示Network Configuration),WrappedTextField(显示描述信息,可自动换行)和StatusField(显示属性名,属性值的关系列表)。

3 XSConsole界面的主要类介绍

如下图所示,主画面所使用的类主要包括:Layout, Dialogue,CursesWindow,DialoguePane,Fields。

3.1 CursesWindow类(XSConsoleCurses.py)

CursesWindow类实际上继承于CursesPane类,用于创建子窗口,可以指定窗口的大小和坐标,以及Title和边框等。实际上,XSConsole是使用curses模块提供的功能来实现字符显示,颜色控制,按键捕获等。首先,调用curses.initscr()创建整个屏幕。然后,调用subwin()创建CursesWindow的子窗口。

AddWrappedText()用于显示字符,可以指定起始坐标,字符串及字符颜色等。

GetKey()用于捕获按键信息。

3.2 Layout类(XSConsoleLayout.py)

Layout,负责控制整个显示画面。

首先,由主程序XSConsoleTerm的Enter()创建一个Layout对象。

self.layout = Layout.NewInst()

然后,调用self.layout.Create()创建TopWindow及MainWindow这两个CursesWindow对象,将主画面分成上下两个子窗口。

最后,self.layout.CreateRootDialogue(…))创建RootDialogue,由RootDialogue(继承于Dialogue类)负责生成MenuPane和StatusPane,并完成其他界面显示的任务。

Layout类可以包含多个CursesWindow和多个Dialogue对象。当界面需要刷新的时候,主程序会调用Layout的Refresh(),如下所示。Layout会依次调用其所包含的CursesWindow和Dialogues的刷新方法。

def Refresh(self):

for window in self.windows:

window.Refresh()

 

for dialogue in self.dialogues:

dialogue.Render()

Layout管理Dialogue对象的方法是使用堆栈的方式,可以使用PushDialogue(),PopDialogue()和TopDialogue()进行操作。最先创建的Dialogue,即RootDialogue,处于堆栈的底部,在刷新画面时会最先被绘制。而堆栈顶部的Dialogue在最后被绘制,所以总显示在最上面。

3.3 Dialogue类(XSConsoleDialogueBases.py)

Dialogue类是XSConsole最主要的界面管理单元。可以说,XSConsole就是基于Dialogue来管理界面显示,按键捕获处理等。

每个Dialogue可以包含多个DialoguePane,每个DialoguePane其实就是一个子窗口,将整个Dialogue分成几个部分,每个部分的界面显示由各个DialoguePane控制。UpdateFields()用于刷新Dialogue的画面。而HandleKey()用于处理主程序传递过来的按键信息。

Dialogue类还包含了几个辅助子类,如FieldArranger,FieldGroup和InputTracker。FieldArranger类用于排列计算Dialogue包含的所有Fields对象的坐标值。FieldGroup类负责将Fields分为BodyFields,StaticFields和InputFields,以区分显示和处理。InputTracker类用于控制光标在不同Field之间的切换。

3.4 DialoguePane类(XSConsoleDialoguePane.py)

每个DialoguePane类都包含一个子窗口,以及多个Fields。当需要在DialoguePane上显示一串字符信息时,可以调用DialoguePane的AddWrappedTextField()方法。如下所示。

def AddWrappedTextField(self, inText, inFlow = None):

self.AddBodyFieldObj(WrappedTextField(inText, self.selectedColour, FirstValue(inFlow, Field.FLOW_RETURN)))

AddWrappedTextField方法增加一个WrappedTextField对象。当DialoguePane调用Render()进行刷新界面时,会调用每个Field对象的Render方法,例如field.Render(win, xpos, ypos),其中win为DialoguePane所指向的子窗口对象。Field的Render方法会在win子窗口的(xpos,ypos)显示其内容。

3.5 Fields类(XSConsoleFields.py)

Fields类算得上是界面显示的最小控制单元。每种不同的Field实现不同的显示效果。

TitleField类,实现标题栏显示。

MenuField类,实现菜单列表的显示。

KeyHelpField类,在窗口底部实现按键信息显示。

WrappedTextField类,可以显示一段字符串信息,根据窗口大小自动换行。

3. LoginDialogue类分析

以LoginDialogue类说明如何创建一个新的Dialogue类,Layout如何管理Dialogue,以及Dialogue是如何工作的。

在未登陆的情况下,执行某些操作时XSConsole会要求用户做帐户验证。这时会弹出LoginDialogue对话框。如下图所示:

启动LoginDialogue的代码如下所示,调用Layout的PushDialogue将新建的LoginDialogue放进Dialogue堆栈。

Layout.Inst().PushDialogue(LoginDialogue(Lang(‘Please log in to perform this function’), inFunc))

再看LoginDialogue的实现代码,主要也就是需要UpdateFields()和HandleKey(),分别负责界面显示和按键处理。__init__()初始化,获得输入参数信息,新建DialoguePane,然后调用UpdateFields()。UpdateFields()分别增加TitleField,用户名输入Field,密码输入Field和按键信息Field,完成整个画面的显示。

当用户触发按键输入时,HandleKey()被调用,并根据不同按键执行相应的操作。当收到‘Escape’按键时,将调用Layout.Inst().PopDialogue()退出该对话框。PopDialogue()将该LoginDialogue从Layout的Dialogue堆栈中弹出。

 

class LoginDialogue(Dialogue):

def __init__(self, inText = None,  inSuccessFunc = None):

Dialogue.__init__(self)

self.text = inText

self.successFunc = inSuccessFunc

pane = self.NewPane(DialoguePane(self.parent))

pane.TitleSet(“Login”)

pane.AddBox()

self.UpdateFields()

pane.InputIndexSet(0)

def UpdateFields(self):

pane = self.Pane()

pane.ResetFields()

if self.text is not None:

pane.AddTitleField(self.text)

pane.AddInputField(Lang(“Username”, 14), “root”, ‘username’)

        pane.AddPasswordField(Lang(“Password”, 14), Auth.Inst().DefaultPassword(), ‘password’)

        pane.AddKeyHelpField( {

Lang(“[Esc]“) : Lang(“Cancel”),

Lang(“[Enter]“) : Lang(“Next/OK”),

Lang(“[Tab]“) : Lang(“Next”)

})

def HandleKey(self, inKey):

handled = True

pane = self.Pane()

if inKey == ‘KEY_ESCAPE’:

Layout.Inst().PopDialogue()

编译nginx + lua 模块出现 could not read symbols

错误显示为:

解决方法在:

修改 objs/Makefile文件

proc_watch