Renaissance—Linux 和 Mac OS X 的跨平台开发工具
Renaissance 是一个免费的开发框架,根据 GNU LGPL 条款许可,用于轻松创建可移植的用户界面。它允许开发者使用开放、简单和标准的 XML 格式来创建丰富的用户界面。
如果不使用 Renaissance,Objective-C 软件开发者将面临无休止的任务,即为 GNUstep(使用 Gorm)和 Mac OS X(使用 Interface Builder)维护其应用程序的视图。随着应用程序的演进和翻译的到位,这可能会成为一个主要的负担,减缓应用程序的开发速度。
幸运的是,Renaissance 框架通过引入许多新概念来创新,以帮助开发者高效地创建可移植的应用程序。这些创新包括:
可移植性:用户界面可以在 Renaissance 已移植的平台上完全重用。目前,它可以在 GNUstep 和 Apple Cocoa 之上重用。
本地化:无需在 GNUstep 和 Mac OS X 下复制界面文件。Renaissance 与 Localizable.strings 文件完美集成。
智能自动布局机制:每个用户界面组件都包含自动化对齐和自动调整大小的智能。这些在处理本地化时尤为重要。
非侵入式集成:Renaissance 易于与当前应用程序代码库集成,因为它使用了与 NIB 文件传统上使用的出口和连接相同的范例。
不幸的是,Renaissance 也有一些缺点。例如,在 GNUstep 和 Mac OS X 上共享一个通用的用户界面可能会导致两个平台都违反人机界面指南 (HIG)。此外,目前无法将 Cocoa 特定的类(如 NSDrawer 和 NSToolbar)与 Renaissance 一起使用。
在本文中,我们使用了为我之前的文章“GNUstep 下的编程——简介”[LJ,2003 年 4 月,/article/6418] 创建的 TIFF 图像查看器的源代码。我们用 Renaissance 框架中创建的视图替换了之前使用 Gorm 和 Interface Builder 创建的视图。您可以从 SSC FTP 站点下载应用程序的源代码 [ftp.linuxjournal.com/pub/lj/listings/issue119/7102.tgz]。
为了在 Linux 下编译和安装 Renaissance,我们首先需要确保 GNUstep 已正确安装。强烈建议使用最新稳定版本的 GNUstep。在撰写本文时,这些版本包括 GNUstep make 1.9.0、GNUstep base 1.9.0、GNUstep GUI 0.9.1 和 GNUstep back 0.9.1。有关安装 GNUstep 的详细说明,请参阅 GNUstep UNIX 系统构建指南(请参阅“资源”)。
一旦 GNUstep 编译并安装完成,您必须通过执行 shell 脚本来加载正确的环境变量集。Bash 用户将使用
. /usr/GNUstep/System/Makefiles/GNUstep.sh
C shell 用户将执行
. /usr/GNUstep/System/Makefiles/GNUstep.csh
最后,要编译和安装 Renaissance,只需解压缩 Renaissance 存档文件并键入(以 root 用户身份)
# cd Renaissance-0.8.0 # make # make install
在 Apple Mac OS X 下,您可以从源代码安装 Renaissance,也可以使用预编译版本。要从源代码安装,您首先必须安装 GNUstep make,然后按照与在 GNUstep 下安装相同的安装步骤进行操作。或者,您可以从 Renaissance 的网站下载二进制版本,解压缩文件并将生成的 Renaissance.framework 文件夹移动到您的 /Library/Frameworks/ 文件夹。我个人推荐后一种选择。
在 2003 年 4 月的 GNUstep 文章中,我们开发了一个简单的 TIFF 图像查看器。对于此应用程序,我们必须在 GNUstep 下使用 Gorm,在 OS X 下使用 Interface Builder 来构建用户界面。幸运的是,Renaissance 的可移植性优势可以帮助我们解决这个负担。由于我们之前的应用程序使用了 Model-View-Controller (MVC) 设计模式,我们可以轻松地使用 Renaissance 重做视图,因为它已经很好地与模型和控制器分离。
重做我们小型应用程序的视图的第一步是创建主 gsmarkup 文件。gsmarkup(GNUstep Renaissance Markup Language 的缩写)文件是用户界面元素应如何创建以及应如何放置在屏幕上并相互连接或与主应用程序中的其他对象连接的简单 XML 表示形式。对于我们的应用程序,主 gsmarkup 文件表示要在 GNUstep 和 Mac OS X 上共享的视图。要创建它,请打开您喜欢的编辑器并创建包含清单 1 所示内容的 TiffViewer.gsmarkup 文件。
清单 1. TiffViewer.gsmarkup
<?xml version="1.0"?> <!DOCTYPE gsmarkup> <gsmarkup> <objects> <window id="window" title="Tiff Viewer" closable="yes"> <hbox> <image id="imageView" scaling="toFit" hasFrame="yes" width="300" height="300" valign="expand" halign="expand"/> </hbox> </window> </objects> <connectors> <outlet source="#NSOwner" target="#window" key="window"/> <outlet source="#NSOwner" target="#imageView" key="imageView"/> </connectors> </gsmarkup>
在清单 1 中,我们告诉 Renaissance 创建一个带有 ID window 的可关闭窗口。然后,我们在该窗口内放置一个图像视图,并设置诸如 300 磅的宽度和高度之类的初始属性。我们还指定我们希望此图像视图可以水平和垂直调整大小。Renaissance 理解这一点,并将信息传播到窗口,使其自动调整大小。然后,我们定义这两个 UI 元素的连接。我们将窗口与我们的 window 出口连接,并将 imageView 与我们的 imageView 出口连接。这两个出口之前已在 AppController.h 文件中定义。
主 gsmarkup 文件创建完成后,我们创建 gsmarkup 文件(清单 2)以保存 GNUstep 下使用的应用程序菜单。在清单 2 中,我们定义了三个菜单项:“加载图像”、“隐藏”和“退出”。它们中的每一个都具有一个关联的操作,如果单击菜单项,则会调用该操作。
清单 2. GNUstep-Menu.gsmarkup
<?xml version="1.0"?> <!DOCTYPE gsmarkup> <gsmarkup> <objects> <menu type="main"> <menuItem title="Load Image" action="loadImage:"/> <menuItem title="Hide" key="h" action="hide:"/> <menuItem title="Quit" key="q" action="terminate:"/> </menu> </objects> </gsmarkup>
创建这两个文件后,我们修改初始 GNUmakefile,并将对 Gorm 文件的引用替换为我们新创建的两个 gsmarkup 文件。我们还在链接框架列表中添加了 Renaissance 框架。GNUmakefile 现在应如清单 3 所示。
清单 3. GNUmakefile
include $(GNUSTEP_MAKEFILES)/common.make APP_NAME = TiffViewer TiffViewer_OBJC_FILES = AppController.m ImageModel.m TiffViewer_RESOURCE_FILES = TiffViewer.gsmarkup \ GNUstep-Menu.gsmarkup ADDITIONAL_GUI_LIBS += -lRenaissance ADDITIONAL_OBJCFLAGS = -Wall -Wno-import include $(GNUSTEP_MAKEFILES)/application.make
然后,我们修改初始 TiffViewerInfo.plist 以删除对 MainMenu.nib 的引用。该文件现在应包含清单 4 所示的内容。
清单 4. TiffViewerInfo.plist
{ ApplicationName = "Tiff Viewer"; ApplicationDescription = "A small image viewer."; }
在编译应用程序之前,我们必须采取的最后一步是在应用程序的控制器中实现两个委托方法。这些方法负责加载主 gsmarkup 文件 (TiffViewer.gsmarkup) 和用于应用程序菜单的文件 (GNUstep-Menu.gsmarkup)。它们需要在 GNUstep 和 Mac OS X 上的应用程序启动时自动调用。为此,请使用编辑器打开 AppController.m 文件并对其进行修改,使其具有清单 5 所示的内容。
清单 5. AppController.m
#import "AppController.h" #import <Renaissance/Renaissance.h> @implementation AppController ... - (void) dealloc { [model release]; [super dealloc]; } - (void) applicationDidFinishLaunching: (NSNotification *) theNotification { [NSBundle loadGSMarkupNamed: @"TiffViewer" owner: self]; } - (void) applicationWillFinishLaunching: (NSNotification *) theNotification { #ifdef GNUSTEP [NSBundle loadGSMarkupNamed: @"GNUstep-Menu" owner: self]; #else [NSBundle loadGSMarkupNamed: @"Cocoa-Menu" owner: self]; #endif } - (void) loadImage: (id)sender { NSOpenPanel *oPanel; int result; oPanel = [NSOpenPanel openPanel]; ...
这里,只添加了两个方法:-applicationDidFinishLaunching: 和 -applicationWillFinishLaunching:。这显示了 Renaissance 的另一个优势——与当前代码库的非侵入式集成。
最后,编译并启动小型应用程序
# make # openapp TiffViewer.app
应用程序启动后,单击“加载图像”菜单项并选择一个 TIFF 文件。它应在窗口中正确显示图像,如图 1 所示。
在 Mac OS X 下,我们与 GNUstep 版本的应用程序共享主 gsmarkup 文件,因此我们现在必须创建用于我们的示例应用程序菜单的 gsmarkup 文件,用于 Mac OS X。这样做允许我们为 Mac OS X 提供不同的菜单,这是必需的,因为 GNUstep 上的菜单布局(垂直)与 Mac OS X 上的菜单布局(水平)不同。创建文件 Cocoa-Menu.gsmarkup,其内容如清单 6 所示。
清单 6. Cocoa-Menu.gsmarkup
<gsmarkup> <objects> <menu type="main"> <menu title="TiffViewer" type="apple"> <menuItem title="Hide TiffViewer" key="h" action="hide:"/> <menuItem title="Quit TiffViewer" key="q" action="terminate:"/> </menu> <menu title="File"> <menuItem title="Load Image" action="loadImage:"/> </menu> </menu> </objects> </gsmarkup>
在清单 6 中,我们还定义了三个菜单项:“隐藏 TiffViewer”、“退出 TiffViewer”和“加载图像”。与 GNUstep 相反,我们在 TiffViewer 菜单下创建前两个,以粗体显示(注意type="apple"),后者在“文件”菜单下创建。我们这样做是因为 Mac OS X 上的菜单布局与 GNUstep 不同,并且我们希望至少在菜单方面遵循 HIG。
创建文件后,我们需要创建 Mac OS X 项目文件并构建应用程序。为此,请启动 Project Builder 应用程序并执行以下步骤
从“文件”菜单中,选择“新建项目...”菜单项,然后选择“Cocoa 应用程序”。单击“下一步”按钮。
指定项目名称 (TiffViewer) 和项目目录,然后单击“完成”按钮。
在“组和文件”面板中选择“类”节点,然后单击“项目”菜单中的“添加文件...”菜单项。添加 AppController.m 和 ImageModel.m 文件。这些文件与 GNUstep 下使用的文件相同。
展开“其他来源”节点并删除 main.m 文件。我们不需要此文件。
展开“资源”节点并双击 MainMenu.nib。这将启动 Interface Builder。从 Interface Builder 的 MainMenu.nib 窗口中,通过单击相应的图标并从“编辑”菜单中选择“删除”来删除 MainMenu 和 Window。保存所有内容,然后退出 Interface Builder。我们需要这样做,因为 Renaissance 可以使用我们的 gsmarkup 文件提供应用程序菜单。
选择“资源”节点并添加 Cocoa-Menu.gsmarkup 和 TiffViewer.gsmarkup 文件,就像您在步骤 3 中所做的那样。
展开“框架和链接框架”节点,然后单击“项目”菜单中的“添加框架...”菜单项。添加位于 /Library/Frameworks 目录中的 Renaissance.framework。
最后,从 Project Builder 的“构建”菜单中,选择“构建并运行”。这将编译并启动应用程序。
正如您在本节中看到的,将应用程序从 GNUstep 移植到 Mac OS X 非常简单。无需更改任何代码。与 GNUstep 下一样,您可以在应用程序中加载 TIFF 文件并尝试调整窗口大小。您应该看到图像视图自动水平和垂直调整大小,如主 gsmarkup 文件中所指定的那样。您还应该注意到应用程序菜单的 Apple 风格水平布局,如图 2 所示。
如前所述,Renaissance 简化了本地化。为了展示如何做到这一点,让我们将我们简单的 TIFF 查看器翻译成法语。Renaissance 自动知道要翻译什么以及要维护什么。在我们的菜单 gsmarkup 文件中,每个菜单项都有一个标题。Renaissance 自动使用 UI 元素的标题作为 Localizable.strings 文件中的键,以获取正确的翻译字符串。为了翻译我们的示例应用程序,请在项目的根目录中创建一个 French.lproj 目录。在该新创建的目录中,创建 Localizable.strings 文件,其内容如清单 7 所示。
清单 7. French.lproj/Localizable.strings
"File" = "Fichier"; "Hide" = "Cacher"; "Hide TiffViewer" = "Cacher TiffViewer"; "Load Image" = "Charger l'image"; "Quit" = "Quitter"; "Quit TiffViewer" = "Quitter TiffViewer";
我们对 GNUstep 和 Mac OS X 使用相同的文件。在 GNUstep 下,修改 GNUmakefile 以添加指令,以便安装我们的翻译资源。以下两行需要添加到 GNUmakefileTiffViewer_LOCALIZED_RESOURCE_FILES = ...和TiffViewer_LANGUAGES = ....
清单 8. 支持本地化所需的 GNUmakefile 更改
... TiffViewer_RESOURCE_FILES = TiffViewer.gsmarkup \ GNUstep-Menu.gsmarkup TiffViewer_LOCALIZED_RESOURCE_FILES = \ Localizable.strings TiffViewer_LANGUAGES = French ADDITIONAL_GUI_LIBS += -lRenaissance ...
最后,在 GNUstep 下,重新编译应用程序以正确复制资源文件,并使用其法语翻译启动它,如下所示
# make # openapp TiffViewer.app -NSLanguages '(French)'
在 Mac OS X 上,您还必须创建 French.lproj 目录和 Localizable.strings 文件(或重用为 GNUstep 创建的文件),其内容如清单 5 所示。创建它们后,请按照以下步骤在 Project Builder 中激活法语本地化
选择“资源”节点,然后从“项目”菜单中选择“添加文件...”,并添加 French.lproj/Localizable.strings 文件。
从“构建”菜单中,单击“构建”。
要在 Mac OS X 下以法语运行应用程序,请从“系统偏好设置”中单击“国际”图标。然后,将“法语”拖到“英语”之前,然后退出应用程序。从 Project Builder 的“调试”菜单中,单击“运行可执行文件”。应用程序应以法语启动。
Renaissance 框架提供了有价值的创新,以帮助开发真正可移植的应用程序。最终,Renaissance 将拥有一个完整的图形编辑器,允许您以图形方式创建 gsmarkup 文件,就像您现在可以使用 Gorm(GNUstep 的图形对象关系建模器)或 Mac OS X 下的 Interface Builder 一样。
在未来的 GNUstep 文章中,我们将增强我们简单的 TIFF 查看器应用程序,使其与 GNUstep 数据库库 (GDL) 一起工作,GDL 是 NeXT 的企业对象框架 (EOF) 的出色免费实现。
资源
GNUstep UNIX 系统构建指南:documents.made-it.com/GNUstep/Build
Objective-C 编程语言:developer.apple.com/techpubs/macosx/Cocoa/ObjectiveC
Ludovic Marcotte 的“GNUstep 下的编程——简介”:/article/6418
Renaissance:www.gnustep.it/Renaissance/index.html
上一篇文章中应用程序的源代码:ftp.linuxjournal.com/pub/lj/listings/issue108/6418.tgz
Ludovic Marcotte (ludovic@inverse.ca) 拥有蒙特利尔大学计算机科学学士学位。他目前是 Inverse, Inc. 的软件架构师,Inverse, Inc. 是一家位于蒙特利尔市中心的小型 IT 咨询公司。