[Jguiraffe-developers] SF.net SVN: jguiraffe:[194] trunk
Brought to you by:
oheger
|
From: <oh...@us...> - 2010-08-26 18:43:59
|
Revision: 194
http://jguiraffe.svn.sourceforge.net/jguiraffe/?rev=194&view=rev
Author: oheger
Date: 2010-08-26 18:43:51 +0000 (Thu, 26 Aug 2010)
Log Message:
-----------
Some improvements of the tutorial application. Added more documentation.
Modified Paths:
--------------
trunk/core/pom.xml
trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/components/model/TreeNodePath.java
trunk/core/src/site/site.xml
trunk/core/src/site/xdoc/overview.xml
trunk/core/src/site/xdoc/userguide/user_guide.xml
trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/components/model/TestTreeNodePath.java
trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/FileSizeTransformer.java
trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/MainWndController.java
trunk/examples/src/main/resources/config.xml
trunk/examples/src/main/resources/main.jelly
trunk/examples/src/main/resources/tutorial-resources.properties
trunk/pom.xml
Added Paths:
-----------
trunk/core/src/site/resources/images/tutorial_main.png
trunk/core/src/site/resources/images/tutorial_viewsettings.png
trunk/core/src/site/xdoc/building.xml
trunk/core/src/site/xdoc/tutorialapp.xml
trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/AbstractDesktopTask.java
trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/EditDesktopTask.java
trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/OpenDesktopTask.java
trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/PrintDesktopTask.java
trunk/examples/src/main/resources/tutorial-resources_de.properties
Property Changed:
----------------
trunk/core/
trunk/examples/
Property changes on: trunk/core
___________________________________________________________________
Added: svn:ignore
+ .externalToolBuilders
.settings
target
.classpath
.project
maven-eclipse.xml
Modified: trunk/core/pom.xml
===================================================================
--- trunk/core/pom.xml 2010-08-22 16:30:32 UTC (rev 193)
+++ trunk/core/pom.xml 2010-08-26 18:43:51 UTC (rev 194)
@@ -101,11 +101,6 @@
</plugin>
<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- </plugin>
-
- <plugin>
<groupId>com.mycila.maven-license-plugin</groupId>
<artifactId>maven-license-plugin</artifactId>
</plugin>
@@ -117,6 +112,12 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.2</version>
+ <configuration>
+ <webAccessUrl>http://jguiraffe.svn.sourceforge.net/viewvc/jguiraffe/trunk</webAccessUrl>
+ <anonymousConnection>scm:svn:https://jguiraffe.svn.sourceforge.net/svnroot/jguiraffe/trunk</anonymousConnection>
+ <developerConnection>scm:svn:https://jguiraffe.svn.sourceforge.net/svnroot/jguiraffe/trunk</developerConnection>
+ </configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -143,4 +144,24 @@
</plugin>
</plugins>
</reporting>
+
+ <profiles>
+ <profile>
+ <id>release</id>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
</project>
Modified: trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/components/model/TreeNodePath.java
===================================================================
--- trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/components/model/TreeNodePath.java 2010-08-22 16:30:32 UTC (rev 193)
+++ trunk/core/src/main/java/net/sf/jguiraffe/gui/builder/components/model/TreeNodePath.java 2010-08-26 18:43:51 UTC (rev 194)
@@ -252,6 +252,81 @@
}
/**
+ * Returns a {@code TreeNodePath} object that was created by appending the
+ * specified {@code ConfigurationNode} to this path. The new node becomes
+ * the target node of the new {@code TreeNodePath} object. This method is
+ * useful when navigating through a tree structure. The passed in node must
+ * be a child node of the current target node.
+ *
+ * @param node the node to be appended to the path
+ * @return the new {@code TreeNodePath} extended by the node
+ * @throws IllegalArgumentException if the passed in node is <b>null</b> or
+ * not a child node of the target node
+ */
+ public TreeNodePath append(ConfigurationNode node)
+ {
+ if (node == null)
+ {
+ throw new IllegalArgumentException("Node must not be null!");
+ }
+ if (node.getParentNode() != getTargetNode())
+ {
+ throw new IllegalArgumentException(
+ "Node is not a child of the target node!");
+ }
+
+ List<ConfigurationNode> newNodes =
+ new ArrayList<ConfigurationNode>(size() + 1);
+ newNodes.addAll(nodes);
+ newNodes.add(node);
+ return new TreeNodePath(newNodes);
+ }
+
+ /**
+ * Returns a {@code TreeNodePath} object that was created by appending the
+ * specified child node of the current target node to this path. This method
+ * determines the child node with the given name and index. It then creates
+ * a new {@code TreeNodePath} object with this node as target node.
+ *
+ * @param childName the name of the child node to be appended
+ * @param index the index of the node (in case there are multiple children
+ * with the same name)
+ * @return the new {@code TreeNodePath} extended by the child node
+ * @throws IllegalArgumentException if no child node with this name can be
+ * found
+ * @throws IndexOutOfBoundsException if the index is invalid
+ */
+ public TreeNodePath append(String childName, int index)
+ {
+ if (childName == null)
+ {
+ throw new IllegalArgumentException(
+ "Name of child node must not be null!");
+ }
+ if (getTargetNode().getChildrenCount(childName) < 1)
+ {
+ throw new IllegalArgumentException("Cannot find child with name "
+ + childName);
+ }
+
+ return append((ConfigurationNode) getTargetNode()
+ .getChildren(childName).get(index));
+ }
+
+ /**
+ * Returns a {@code TreeNodePath} object that was created by appending the
+ * first child node of the current target node with the given name to this path.
+ * This is a short cut of {@code append(childName, 0)}.
+ * @param childName the name of the child node to be appended
+ * @return the new {@code TreeNodePath} extended by the child node
+ * @throws IllegalArgumentException if no child node with this name can be found
+ */
+ public TreeNodePath append(String childName)
+ {
+ return append(childName, 0);
+ }
+
+ /**
* Tests whether two objects are equal. Two path objects are considered
* equal if and only if they refer to the same target node.
*
Added: trunk/core/src/site/resources/images/tutorial_main.png
===================================================================
(Binary files differ)
Property changes on: trunk/core/src/site/resources/images/tutorial_main.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Added: trunk/core/src/site/resources/images/tutorial_viewsettings.png
===================================================================
(Binary files differ)
Property changes on: trunk/core/src/site/resources/images/tutorial_viewsettings.png
___________________________________________________________________
Added: svn:mime-type
+ image/png
Modified: trunk/core/src/site/site.xml
===================================================================
--- trunk/core/src/site/site.xml 2010-08-22 16:30:32 UTC (rev 193)
+++ trunk/core/src/site/site.xml 2010-08-26 18:43:51 UTC (rev 194)
@@ -39,8 +39,10 @@
<item name="Home" href="/index.html"/>
<item name="Overview" href="/overview.html"/>
<item name="Javadoc (latest)" href="/apidocs/index.html"/>
+ <item name="User's Guide" href="/userguide/user_guide.html"/>
+ <item name="Tutorial application" href="/tutorialapp.html"/>
<item name="SVN" href="http://jguiraffe.svn.sourceforge.net/viewvc/jguiraffe/"/>
- <item name="User's Guide" href="/userguide/user_guide.html"/>
+ <item name="Building from SVN" href="/building.html"/>
</menu>
${reports}
Added: trunk/core/src/site/xdoc/building.xml
===================================================================
--- trunk/core/src/site/xdoc/building.xml (rev 0)
+++ trunk/core/src/site/xdoc/building.xml 2010-08-26 18:43:51 UTC (rev 194)
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright 2006-2010 The JGUIraffe Team.
+
+ Licensed under the Apache License, Version 2.0 (the "License")
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!-- $Id$ -->
+<document>
+
+ <properties>
+ <author email="oh...@us...">Oliver Heger</author>
+ <title>Building from SVN</title>
+ </properties>
+
+<body>
+ <section name="Building from Subversion">
+ <p>
+ <em>JGUIraffe</em> uses <a href="http://maven.apache.org">Apache Maven</a>
+ as its build tool. When you check out the source code from
+ <a href="http://subversion.apache.org/">Subversion</a> using the command
+ </p>
+ <source><![CDATA[
+svn co https://jguiraffe.svn.sourceforge.net/svnroot/jguiraffe/trunk jguiraffe
+ ]]></source>
+ <p>
+ you get a maven aggregator project with the following modules:
+ <ul>
+ <li><code>core</code> is the actual library. The jar file created when
+ building this project is the one which needs to be present in the class
+ path of your application.</li>
+ <li><code>examples</code> contains some sample code and also the complete
+ tutorial application.</li>
+ </ul>
+ </p>
+ <p>
+ For convenience the top-level directory contains a <code>pom.xml</code> for
+ building the whole project including all its modules. Just execute the
+ following command in this directory:
+ </p>
+ <source><![CDATA[
+mvn clean install
+ ]]></source>
+ <p>
+ This requires a JDK 1.6 because the <code>examples</code> module uses some
+ 1.6 features. The <code>core</code> is compatible with JDK 1.5. It can be
+ built with a 1.5 compiler by issuing the same command in the <code>core</code>
+ subdirectory. The resulting jar file containing all classes of the
+ <em>JGUIraffe</em> library can be found in the <code>core/target</code>
+ folder.
+ </p>
+ <p>
+ <em>Note:</em> If you get an <code>OutOfMemoryError</code>, you have to
+ increase the heap size for the Maven build. This can be achieved by setting
+ the <em>MAVEN_OPTS</em> environment variable correspondingly, e.g.
+ <code>MAVEN_OPTS=-Xmx256m</code> would increase the size of the heap space
+ to 256 M.
+ </p>
+ <p>
+ The pom defines a profile named <em>release</em> which creates some
+ additional artifacts. If it is activated, jars with Javadocs and the
+ project's sources are produced. These jars can be integrated in typical IDEs.
+ To activate this profile and generate the additional artifacts enter the
+ following command (either in the top-level or in the <code>core</code>
+ directory):
+ </p>
+ <source><![CDATA[
+mvn clean install -P release
+ ]]></source>
+ </section>
+</body>
+
+</document>
Property changes on: trunk/core/src/site/xdoc/building.xml
___________________________________________________________________
Added: svn:mime-type
+ text/xml
Added: svn:keywords
+ Date Author Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/core/src/site/xdoc/overview.xml
===================================================================
--- trunk/core/src/site/xdoc/overview.xml 2010-08-22 16:30:32 UTC (rev 193)
+++ trunk/core/src/site/xdoc/overview.xml 2010-08-26 18:43:51 UTC (rev 194)
@@ -17,6 +17,7 @@
-->
+<!-- $Id$ -->
<document>
<properties>
Added: trunk/core/src/site/xdoc/tutorialapp.xml
===================================================================
--- trunk/core/src/site/xdoc/tutorialapp.xml (rev 0)
+++ trunk/core/src/site/xdoc/tutorialapp.xml 2010-08-26 18:43:51 UTC (rev 194)
@@ -0,0 +1,525 @@
+<?xml version="1.0"?>
+<!--
+
+ Copyright 2006-2010 The JGUIraffe Team.
+
+ Licensed under the Apache License, Version 2.0 (the "License")
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+
+<!-- $Id$ -->
+<document>
+
+ <properties>
+ <author email="oh...@us...">Oliver Heger</author>
+ <title>The tutorial application</title>
+ </properties>
+
+<body>
+ <section name="The tutorial application">
+ <p>
+ In the source code repository, next to the code of the actual library, there
+ is a module with sample code. It is named <em>examples</em>. The major part
+ of this module consists of an example application demonstrating many of the
+ features offered by the <em>JGUIraffe</em> library. This section describes
+ the tutorial application. It is intended to be an extension of the
+ <a href="userguide/user_guide.html">user's guide</a>. While the user's guide
+ provides a whole lot of background information, this document is more
+ focused on practical things. It can also be used to get a quick jump start
+ into development with the <em>JGUIraffe</em> library.
+ </p>
+
+ <subsection name="Features of the tutorial application">
+ <p>
+ The tutorial application is not designed to be used as a productive tool.
+ Rather, its goal is to demonstrate typical programming practices working well
+ with the <em>JGUIraffe</em> library. This manifests itself in the fact that
+ many features - especially "dangerous" operations like removing
+ files - have not been implemented. As problem domain a file system browser
+ application was chosen. The following screenshot shows the main window of
+ the application:
+ </p>
+ <img src="images/tutorial_main.png"
+ alt="Main window of the tutorial application"/>
+ <p>
+ The application follows typical UI conventions of directory browsing tools.
+ The main panel (below the menu and the tool bar) is split into two areas.
+ On the left hand site there is a combo box allowing the user to select a
+ root file system. On Windows systems it contains the drive letters
+ available. Below the combo box there is a tree view component displaying
+ the directory structure of the file system currently selected. On the right
+ hand site there is a table showing the content (the sub directories and
+ files) of the directory selected in the tree view on the left.
+ </p>
+ <p>
+ From the tool bar or the main menu some operations can be triggered to do
+ something with the file(s) selected. The availability of these operations
+ depends on the current selection. For instance, a group of actions is active
+ only if a single file is selected. When selecting the <em>View settings...</em>
+ menu item from the <em>Extras</em> menu a dialog window pops up allowing the
+ definition of view-related properties for the current directory:
+ </p>
+ <img src="images/tutorial_viewsettings.png"
+ alt="Dialog window with view settings"/>
+ <p>
+ Using this dialog window many details of the display of the current directory
+ can be specified, for instance colors, the sorting of the files and sub
+ directories, and filter conditions. The settings entered in this dialog
+ window are saved in a file in the directory so that they can be applied
+ whenever the user navigates to this directory.
+ </p>
+ <p>
+ An action <em>File new</em> available from both the main menu and the tool
+ bar allows the creation of a new file. It displays a dialog window in which
+ the user can enter a file name and text content of the file. Closing this
+ window with the OK button creates such a file in the current directory. This
+ dialog window and the builder script which defines it is also subject of the
+ chapter <a href="userguide/builderscript.html">A complete builder script</a>
+ of the user's guide.
+ </p>
+ <p>
+ There is another action which demonstrates dealing with long-running
+ operations: If <em>Extras / Long operation</em> is selected, a dialog window
+ appears which allows the configuration of a dummy background task - mainly
+ the duration of the task in seconds can be entered using a slider control.
+ When the dialog window is closed the task runs in the background (it does
+ nothing useful), and another window is displayed showing the progress of the
+ task.
+ </p>
+ </subsection>
+
+ <subsection name="Quick start">
+ <p>
+ A <em>JGUIraffe</em> application requires a minimum set of files in order to
+ successfully launch it and to configure the framework. Of course, these
+ files are present for the tutorial application, too. We provide an overview
+ over these files here. This is especially useful for the impatient readers,
+ so they can start with their own experiments.
+ </p>
+ <p>
+ Each Java application needs a startup class, i.e. a class containing a
+ <code>main()</code> method. A <em>JGUIraffe</em> application does not
+ strictly require a custom startup class because the
+ <code><a href="apidocs/net/sf/jguiraffe/gui/app/Application.html">
+ Application</a></code> class comes with a <code>main()</code> method which can
+ be used out of the box. However, providing an application-specific startup
+ class can simplify some things, e.g. the definition of launch configurations
+ in an IDE. If the application supports command line arguments, a custom
+ startup class is also required. For these reasons the tutorial application
+ comes with its own startup class, but with a very simple one. It is derived
+ from <code>Application</code> and just calls the corresponding method to get
+ the framework running:
+ </p>
+ <source><![CDATA[
+package net.sf.jguiraffe.examples.tutorial;
+
+import net.sf.jguiraffe.gui.app.Application;
+import net.sf.jguiraffe.gui.app.ApplicationException;
+
+public class Main extends Application
+{
+ /**
+ * The main method of the application. Starts the whole application.
+ * @param args command line arguments
+ */
+ public static void main(String[] args) throws ApplicationException
+ {
+ startup(new Main(), args);
+ }
+}
+ ]]></source>
+ <p>
+ You may wonder how the framework knows which main window to display. The
+ startup class does not contain any information about this. The answer is
+ that this information is obtained from the application's configuration.
+ <em>JGUIraffe</em> uses <a href="http://commons.apache.org/configuration">
+ Apache Commons Configuration</a> to manage configuration data. So a
+ configuration file compatible with this library has to be created. Actually,
+ two configuration files are needed: One file is a description file listing
+ several configuration sources. This file is named <em>config.xml</em> per
+ default and is searched in the class path. The other file contains the
+ actual configuration of the <em>JGUIraffe</em> framework; it is referenced
+ from the first file. The <em>config.xml</em> file looks as follows for the
+ tutorial application:
+ </p>
+ <source><![CDATA[
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<configuration>
+ <system config-name="system-config"/>
+ <xml config-name="userConfig" fileName="${user.home}/.jguiraffe-testappconfig.xml"
+ config-optional="true" config-forceCreate="true"/>
+ <additional>
+ <xml fileName="framework-config.xml"/>
+ </additional>
+</configuration>
+ ]]></source>
+ <p>
+ Here, in the section wrapped by the <code><additional></code> tags
+ the actual configuration file for the framework - in this case named
+ <em>framework-config.xml</em> - is defined. The other elements integrate
+ some other configuration sources (which are useful, but not required for an
+ application):
+ <ul>
+ <li>The <code><system></code> element makes Java system properties
+ available to the configuration system.</li>
+ <li>This is used by the following <code><xml></code> tag which defines
+ an XML configuration file named <em>.jguiraffe-testappconfig.xml</em>
+ located in the home directory of the current user. In this file data
+ specific to a user can be stored; for instance, the framework stores here
+ the position and the size of the main window, so on the next start of the
+ application these properties can be restored.</li>
+ </ul>
+ The configuration of the framework is stored in the
+ <em>framework-config.xml</em> file. Here also a minimum set of properties
+ must be defined so that the framework knows what to do:
+ </p>
+ <source><![CDATA[
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<config>
+ <framework>
+ <builder>
+ <mainScript>main.jelly</mainScript>
+ <beandefinitions>
+ <beandefinition>tutorial-beans.jelly</beandefinition>
+ </beandefinitions>
+ </builder>
+ <appctx>
+ <defaultResourceGroup>tutorial-resources</defaultResourceGroup>
+ </appctx>
+
+ <storeuserconfig>true</storeuserconfig>
+ <userconfigname>userConfig</userconfigname>
+ </framework>
+</config>
+ ]]></source>
+ <p>
+ The most important piece of information is the name of the builder script
+ defining the application's main window. It is defined by the
+ <code><mainScript></code> element. The other elements configure some
+ useful but optional functionality of the framework. We give a short overview
+ over these elements:
+ <ul>
+ <li>When starting an application an arbitrary number of files with bean
+ definitions can be read. The beans defined in these files can then be
+ queried from the application's global <code>BeanContext</code>. This is
+ useful for instance for central services. For each bean definition file to
+ be read a <code><beandefinition></code> element has to be added.</li>
+ <li>If an application uses localized strings, it can define the default
+ resource group using the <code><defaultResourceGroup></code>
+ element. The default resource group is used for each resource lookup if
+ no specific group is provided.</li>
+ <li>The remaining elements define the so-called <em>user configuration</em>.
+ This is the already mentioned configuration source in which user-specific
+ data is stored. Here we specify that this mechanism should be enabled
+ (<code><storeuserconfig>true</storeuserconfig></code>) and
+ which configuration source to use for this purpose. The name of the
+ configuration source is passed to the <code><userconfigname></code>
+ element and must match a configuration source which was defined in the
+ main configuration description file <em>config.xml</em>.</li>
+ </ul>
+ </p>
+ <p>
+ This is basically all what is needed for a working <em>JGUIraffe</em>
+ application. Well, of course, the main builder script referenced by the
+ framework configuration file must also exist; this is highly specific to a
+ concrete application.
+ </p>
+ <p>
+ Applications that use resources to translate texts will also ship with a set
+ of resource properties files (provided that the default resource manager
+ implementation is used which obtains resource texts from properties files).
+ The tutorial application belongs to this group of applications. Its base
+ resource bundle is named <em>tutorial-resources.properties</em>. (Note that
+ the name matches the default resource group specified in the framework
+ configuration. In the case of the default resource manager a resource group
+ corresponds to a resource properties file. The properties file for the
+ default language does not have an extension; the file with the German
+ translations is named <em>tutorial-resources_de.properties</em>.)
+ </p>
+ </subsection>
+
+ <subsection name="Packaging">
+ <p>
+ Before we start with the actual exploration of the tutorial application we
+ will have to say some words about its package structure. There are multiple
+ reasonable ways of packaging a UI application. For instance, classes could
+ be grouped together in packages by their type. So you would end up with
+ packages for model classes, controller classes, view classes, helper classes,
+ etc. This is a valid packaging scheme, and it can be applied to
+ <em>JGUIraffe</em> applications.
+ </p>
+ <p>
+ The tutorial application uses a different approach. It groups its classes by
+ functionality. This means that there are packages related to the main UI
+ elements (the main frame and the dialog windows) used by the application.
+ (There is also a package with shared classes used by multiple windows.)
+ This way of packaging is also suitable for <em>JGUIraffe</em> applications.
+ The programming model of this framework typically leads to multiple small
+ classes implementing specific functionality like event handling or task
+ execution. View classes are not needed because views are defined in builder
+ scripts. In many cases you do not even have a controller class because the
+ default implementation of the framework is sufficient. So it makes sense to
+ bundle the classes that implement logic for a specific window in a common
+ package. By the way, these small and focused classes are much easier to
+ unit test than large, monolitic view classes with lots of nested anonymous
+ event listener classes.
+ </p>
+ </subsection>
+
+ <subsection name="The main frame">
+ <p>
+ The classes related to the application's main frame are all located in the
+ <code>net.sf.jguiraffe.examples.tutorial.mainwnd</code> package. In addition
+ to the main controller class, <code>MainWndController</code>, the package
+ contains a bunch of helper classes, e.g. for processing events or for
+ serving as model objects for UI elements. The frame window itself is
+ constructed from the builder script <code>main.jelly</code> which can be
+ found in the <code>src/main/resources</code> directory. (This is the maven
+ default directory for non-Java files which have to be added to the generated
+ jar. Here all builder scripts, configuration files and resource bundles are
+ stored.)
+ </p>
+ <p>
+ <code>MainWndController</code> is responsible for most of the logic of the
+ main frame window. This is different from typical controller implementations
+ for dialog windows: a dialog window is mainly concerned with gathering data
+ from the user and processing the results. The application's main frame
+ window serves a different purpose. Therefore the controller class is very
+ specific to the logic of the application. It is not associated with the
+ frame in the usual way, and it does not extend the controller base class
+ defined by the <em>JGUIraffe</em> framework (which is focused on dialog
+ windows). The association between the controller object and the UI is done
+ by the dependency injection framework. The controller is passed references
+ to all UI elements it has to interact with. Analogously, all helper objects
+ (e.g. event listeners) which have to call back the controller are passed a
+ reference to it. The helper objects are very simple: they store a reference
+ to the controller and call a corresponding method when they are triggered.
+ Thus the view logic for handling the interaction between the UI elements can
+ be implemented centrally in the <code>MainWndController</code> class.
+ </p>
+ <p>
+ The <code>main.jelly</code> builder script is a bit more complex than scripts
+ defining dialog windows because it is also responsible for the application's
+ main menu, its tool bar, and the actions representing menu items and/or
+ tool bar buttons. These action declarations make up a large section in the
+ builder script. Another big part defines the UI of the window: the combo
+ box for the file system, the tree view with the directory tree, and the
+ table with the current directory's content. The remaining parts define
+ helper objects and plug them together.
+ </p>
+ <p>
+ <code>MainWndController</code> is notified when the selection of the combo
+ box with the root file systems changes. This is done by the
+ <code>FileSystemChangeListener</code> class. In response of this event the
+ controller has to update the tree view so that it shows the content of the
+ newly selected file system. As the tree view's model a
+ <code>HierarchicalConfiguration</code> object from the
+ <a href="http://commons.apache.org/configuration">Apache Commons
+ Configuration</a> library is used. A configuration node in this model object
+ represents a node that is displayed by the tree view. The controller stores
+ the configuration nodes associated with root file elements. So it can
+ detect whether it already has loaded data for a file system or whether it
+ has to load this data now. In any case the model of the tree view is
+ manipulated so that it points to the data of the newly selected file system.
+ </p>
+ <p>
+ The controller also has to be notified about changes in the selection of
+ the tree view. When the user navigates the tree the corresponding directory
+ has to be displayed in the table. Because a whole file system can become
+ pretty huge, the controller does not load it at once. Rather, only a single
+ layer (a directory with its files and subdirectories) is loaded. If a
+ directory is selected whose content has not yet been loaded, the controller
+ executes a command of type <code>ReadDirectoryCommand</code> in the
+ background. The command reads the content of the directory and performs the
+ corresponding sort and filter operations. On completion of the command the
+ model of the tree view is updated. The configuration nodes forming the tree's
+ model are associated with objects of type <code>DirectoryData</code> from
+ the <code>model</code> package. They contain the data required for the
+ display of a directory. Such an object is determined during the processing
+ of the selection changed event of the tree view - either it has already been
+ present in the model or it has just been created by a
+ <code>ReadDirectoryCommand</code>. It is then used to populate the table.
+ </p>
+ <p>
+ The data model of the table is a plain <code>java.util.ArrayList</code>. It
+ is filled from the data of the <code>DirectoryData</code> object obtained
+ from the tree view's model. Actually, the list contains objects of type
+ <code>net.sf.jguiraffe.examples.tutorial.model.FileData</code>, a simple
+ wrapper around a <code>java.io.File</code> object. The table is configured
+ to display the single properties of such <code>FileData</code> objects.
+ With the <code>FileSizeTransformer</code> class there is a special
+ transformer implementation applied to the column with the file size: it
+ displays the size in kilo bytes.
+ </p>
+ </subsection>
+
+ <subsection name="The view settings dialog">
+ <p>
+ The classes implementing the view settings dialog are located in the
+ <code>net.sf.jguiraffe.examples.tutorial.viewset</code> package; the
+ builder script defining the dialog window is named
+ <em>viewsettings.jelly</em>. While the main frame demonstrates usage of some
+ of the advanced UI elements like trees and tables, the view settings dialog
+ contains various types of simple controls, e.g. radio buttons, checkboxes,
+ or input elements for other data types like numbers or dates.
+ </p>
+ <p>
+ The view settings dialog is a typical dialog window whose purpose is to
+ enter data. Therefore the base classes provided by the <em>JGUIraffe</em>
+ library for forms and controllers can be used. Because the UI has some
+ dynamic aspects, there is a custom controller implementation named
+ <code>ViewSettingsFormController</code> derived from the base class
+ <code>FormController</code>. This controller class has the task to control
+ the enabled state of some input elements which depent on the state of other
+ elements. This is achieved by registering the controller object as listener
+ for change events at the checkbox elements defined in the UI (registration
+ is performed in a declarative way by tags in the builder script). These
+ checkboxes are connected to input elements; the input elements are only
+ enabled if the checkbox is selected. Therefore, when a change event is
+ received, the controller determines the affected checkbox from the event's
+ properties and obtains its selection state. It then maps the name of the
+ checkbox to a component group and sets the enabled state of this group
+ accordingly. The UI has been defined in a way that there are component
+ groups for the elements which depend on checkboxes. So it is easy to find
+ the elements affected by a change of a checkbox and to manipulate their
+ state.
+ </p>
+ <p>
+ When the user closes the view settings dialog by clicking the OK button a
+ command of type <code>CreateViewSettingsCommand</code> is executed. It
+ creates a file in the current directory and stores the settings the user has
+ entered in the dialog window in it. To do this the command needs some data:
+ <ul>
+ <li>The data model of the form - an object of type
+ <code>ViewSettings</code> lives in the current bean context. It has been
+ stored there by the command which opened the view settings dialog.
+ <code>ViewSettings</code> is a pretty simple data class. It has methods
+ for loading and storing instances using standard Java serialization
+ facilities.</li>
+ <li>The current directory must be known because in this directory the
+ <code>ViewSettings</code> instance has to be stored. It is obtained from
+ the central <code>ApplicationContext</code> object. The application context
+ allows access to so-called typed properties which are intended to be used
+ for managing central data required by multiple parts of the application.
+ The controller of the main window sets this property whenever the user
+ selects a new directory in the tree view.</li>
+ </ul>
+ After the command has written the file with the view settings it executes
+ the <em>Refresh</em> action. This basically simulates a click on the
+ corresponding tool bar icon. It causes another <code>ReadDirectoryCommand</code>
+ to be executed so that the content of the current directory is read again.
+ The <code>ReadDirectoryCommand</code> class is able to interprete the view
+ settings for the current directory and apply filters and sort order
+ accordingly.
+ </p>
+ </subsection>
+
+ <subsection name="A long-running operation">
+ <p>
+ Applications sometimes have the requirement to execute a task which may take
+ a while. In such cases it is good practice to give the user some feedback
+ about what is going on. A good choice for this purpose is a dialog window
+ with a progress indicator. If possible, a cancel button can be provided
+ which allows the user to cancel the operation.
+ </p>
+ <p>
+ The tutorial application defines an action that simulates such a long-running
+ task. The implementation demonstrates how standard means provided by
+ <em>JGUIraffe</em> can be used to implement a dialog window for visual
+ feedback. The corresponding classes can be found in the
+ <code>net.sf.jguiraffe.examples.tutorial.bgtask</code> package, there is
+ also builder script named <em>bgtask.jelly</em>.
+ </p>
+ <p>
+ The builder script is a little bit special because it defines two dialog
+ windows at once. The main dialog window is directly opened when the user
+ selects the action for the long-running task. It presents some options for
+ the configuration of the task - mainly the user can specify the duration
+ using a slider control. (<em>Note:</em> There is also a checkbox which
+ controls whether visual feedback is enabled, but this is only for testing
+ purposes. A real application should probably always provide feedback.
+ Actually, disabling visual feedback is used to test the behavior of the
+ application if it is to be terminated and there is still a background task
+ running. You can try what happens then.)
+ </p>
+ <p>
+ When closing the configuration dialog with OK an instance of the
+ <code>BgTaskCommand</code> class is executed. This object is passed some
+ references to helper and data objects via dependency injection:
+ <ul>
+ <li>The <code><a href="apidocs/net/sf/jguiraffe/gui/builder/utils/GUISynchronizer.html">
+ GUISynchronizer</a></code> object is required for accessing UI elements
+ from a different thread than the event dispatch thread. The command object
+ is executed in a background thread, so it has to use the synchronizer when
+ it needs to manipulate the UI.</li>
+ <li>A reference to the second dialog window defined by the builder script.
+ This is the dialog for giving feedback about the progress of the
+ operation.</li>
+ <li>The data model of the first dialog window. This is a bean storing the
+ data entered by the user in the configuration dialog.</li>
+ <li>A reference to the progress bar control contained in the feedback
+ dialog. The command object uses this reference to increase the progress
+ indicator.</li>
+ </ul>
+ </p>
+ <p>
+ At the beginning of its <code>execute()</code> method the command class
+ opens the dialog window for the feedback of the operation. Then it simulates
+ a long-running operation. This is done in a loop which sleeps for one
+ second until the duration specified by the user is reached. In each iteration
+ the current progress rate is calculated, and the progress indicator is
+ updated correspondingly. Because the command runs in a background thread
+ the <code>GUISynchronizer</code> has to be used for this purpose.
+ </p>
+ <p>
+ After completion of the <code>execute()</code> method the
+ <code>performGUIUpdate()</code> method is called automatically in the event
+ dispatch thread. Here the feedback dialog window is closed.
+ </p>
+ <p>
+ The command class also implements the <code>FormActionListener</code>
+ interface and is registered as action listener at the <em>Cancel</em>
+ button of the feedback dialog (via an <code><a:eventListener></code>
+ tag in the builder script). So it gets notified when the user wishes to
+ cancel the operation. In this case the <em>Cancel</em> button is disabled -
+ to show the user that the click was recognized -, and a flag is set which
+ causes the main loop of the command to terminate.
+ </p>
+ <p>
+ What is only simulated by the <code>BgTaskCommand</code> class can be
+ transferred to real world use cases. The handling of the dialog window for
+ the feedback of the operation can be done in a similar way. Then the task
+ to be performed has to be broken down into several steps so that the
+ progress indicator can be updated in a meaningful way. Listening to a cancel
+ button and terminating the operation on demand is probably desired in most
+ cases, too.
+ </p>
+ <p>
+ Note that for this kind of operations the feedback dialog is an essential
+ implementation element. It does not only show the progress of the operation
+ but also blocks the UI (it is a modal dialog) and prevents the user to
+ trigger further actions. This is desired because in many use cases the user
+ should not be allowed to start multiple background tasks in parallel which
+ may conflict with each other. In <em>JGUIraffe</em> applications it is per
+ default not possible to start multiple background tasks at once anyway
+ because the command queue is only associated with a single worker thread. So
+ tasks are executed one by one in isolation. If an application really needs a
+ task that should run in the background independent from all other tasks of
+ the application, it has to start a separate thread manually.
+ </p>
+ </subsection>
+ </section>
+</body>
+
+</document>
Property changes on: trunk/core/src/site/xdoc/tutorialapp.xml
___________________________________________________________________
Added: svn:mime-type
+ text/xml
Added: svn:keywords
+ Date Author Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/core/src/site/xdoc/userguide/user_guide.xml
===================================================================
--- trunk/core/src/site/xdoc/userguide/user_guide.xml 2010-08-22 16:30:32 UTC (rev 193)
+++ trunk/core/src/site/xdoc/userguide/user_guide.xml 2010-08-26 18:43:51 UTC (rev 194)
@@ -30,12 +30,25 @@
<section name="About this document">
<p>
- This document contains user documentation about the JGUIraffe library.
+ This document contains user documentation about the <em>JGUIraffe</em>
+ library. It covers all important features of the library and provides
+ many usage examples.
</p>
<p>
- <em>Note: This is work in progress. This guide is currently incomplete.
- New documentation will be added when it becomes available.</em>
+ In most cases the single chapters of this user's guide are self contained.
+ We tried to arrange them in a meaningful order, but forward references
+ could not always be avoided. The sections about builders (starting from
+ the chapter <a href="builders.html">Introducing builders</a>) build upon
+ each other, so they should be read in sequence best.
</p>
+ <p>
+ In addition to this guide <em>JGUIraffe</em> ships with a tutorial
+ application. The associated <a href="../tutorialapp.html">documentation</a>
+ is a good extension of the documentation provided here. Especially the
+ <a href="../tutorialapp.html#Quick_start">Quick start</a> sub section is a
+ good starting point for the impatient readers. It describes the minimum
+ artifacts required to get a <em>JGUIraffe</em> application up and running.
+ </p>
</section>
<section name="Table of contents">
Modified: trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/components/model/TestTreeNodePath.java
===================================================================
--- trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/components/model/TestTreeNodePath.java 2010-08-22 16:30:32 UTC (rev 193)
+++ trunk/core/src/test/java/net/sf/jguiraffe/gui/builder/components/model/TestTreeNodePath.java 2010-08-26 18:43:51 UTC (rev 194)
@@ -58,8 +58,15 @@
}
};
+ /** Constant for the prefix path of the test key. */
+ private static final String PATH_PREFIX = "tables(0).table(1)";
+
+ /** Constant for the name of a child node. */
+ private static final String CHILD_NAME = "field";
+
/** Constant for the test key. */
- private static final String TEST_KEY = "tables(0).table(1).field(2)";
+ private static final String TEST_KEY = PATH_PREFIX + "." + CHILD_NAME
+ + "(2)";
/** Stores the root of the test node hierarchy. */
private static ConfigurationNode root;
@@ -81,7 +88,7 @@
for (int j = 0; j < TABLE_FIELDS[i].length; j++)
{
ConfigurationNode ndField = new DefaultConfigurationNode(
- "field", TABLE_FIELDS[i][j]);
+ CHILD_NAME, TABLE_FIELDS[i][j]);
ndTab.addChild(ndField);
}
}
@@ -298,6 +305,24 @@
}
/**
+ * Helper method for testing whether a path object contains the expected
+ * nodes.
+ *
+ * @param expected a list with the expected nodes
+ * @param path the path to check
+ */
+ private void checkPathNodes(List<ConfigurationNode> expected,
+ TreeNodePath path)
+ {
+ List<ConfigurationNode> actual = path.getNodes();
+ assertEquals("Wrong size of path", expected.size(), actual.size());
+ for (int i = 0; i < expected.size(); i++)
+ {
+ assertSame("Wrong node at " + i, expected.get(i), actual.get(i));
+ }
+ }
+
+ /**
* Tests whether the parent path can be obtained.
*/
@Test
@@ -305,14 +330,8 @@
{
TreeNodePath path = new TreeNodePath(nodeForKey(TEST_KEY));
TreeNodePath parent = path.parentPath();
- assertEquals("Wrong size of parent path", path.size() - 1, parent
- .size());
List<ConfigurationNode> nodes1 = path.getNodes();
- List<ConfigurationNode> nodes2 = parent.getNodes();
- for (int i = 0; i < parent.size(); i++)
- {
- assertSame("Wrong node at " + i, nodes1.get(i), nodes2.get(i));
- }
+ checkPathNodes(nodes1.subList(0, nodes1.size() - 1), parent);
assertSame("Wrong parent node", path.getNodes().get(path.size() - 2),
parent.getTargetNode());
}
@@ -327,4 +346,99 @@
TreeNodePath path = new TreeNodePath(root);
path.parentPath();
}
+
+ /**
+ * Tests whether a node can be appended to a path.
+ */
+ @Test
+ public void testAppendNode()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ ConfigurationNode child =
+ (ConfigurationNode) path.getTargetNode().getChildren().get(0);
+ TreeNodePath path2 = path.append(child);
+ assertSame("Wrong target node", child, path2.getTargetNode());
+ List<ConfigurationNode> nodes =
+ new ArrayList<ConfigurationNode>(path.getNodes());
+ nodes.add(child);
+ checkPathNodes(nodes, path2);
+ }
+
+ /**
+ * Tries to append a null node to a path.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAppendNodeNull()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ path.append((ConfigurationNode) null);
+ }
+
+ /**
+ * Tries to append a configuration node to a path which is not a child node
+ * of the current target node.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAppendNodeNoChild()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ path.append(new DefaultConfigurationNode());
+ }
+
+ /**
+ * Tests whether a child node can be appended to a path.
+ */
+ @Test
+ public void testAppendChild()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ TreeNodePath path2 = path.append(CHILD_NAME, 1);
+ List<ConfigurationNode> nodes =
+ new ArrayList<ConfigurationNode>(path.getNodes());
+ ConfigurationNode nd = nodeForKey(PATH_PREFIX);
+ nodes.add((ConfigurationNode) nd.getChildren(CHILD_NAME).get(1));
+ checkPathNodes(nodes, path2);
+ }
+
+ /**
+ * Tests whether the first child node is used if no index is provided.
+ */
+ @Test
+ public void testAppendChildDefaultIdx()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ TreeNodePath path2 = path.append(CHILD_NAME);
+ assertEquals("Wrong node added", TABLE_FIELDS[1][0], path2
+ .getTargetNode().getValue());
+ }
+
+ /**
+ * Tries to add a null child to a path.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAppendChildNull()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ path.append((String) null);
+ }
+
+ /**
+ * Tries to add an unknown child node to a path.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testAppendChildUnknown()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ path.append("an unknown child!");
+ }
+
+ /**
+ * Tries to add a child with an invalid index to a path.
+ */
+ @Test(expected = IndexOutOfBoundsException.class)
+ public void testAppendChildInvalidIndex()
+ {
+ TreeNodePath path = new TreeNodePath(nodeForKey(PATH_PREFIX));
+ path.append(CHILD_NAME, TABLE_FIELDS[1].length + 1);
+ }
}
Property changes on: trunk/examples
___________________________________________________________________
Added: svn:ignore
+ .externalToolBuilders
.settings
target
.classpath
.project
maven-eclipse.xml
Added: trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/AbstractDesktopTask.java
===================================================================
--- trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/AbstractDesktopTask.java (rev 0)
+++ trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/AbstractDesktopTask.java 2010-08-26 18:43:51 UTC (rev 194)
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2006-2010 The JGUIraffe Team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.jguiraffe.examples.tutorial.mainwnd;
+
+import java.awt.Desktop;
+import java.io.File;
+import java.util.List;
+
+import net.sf.jguiraffe.gui.builder.utils.MessageOutput;
+import net.sf.jguiraffe.gui.cmd.CommandBase;
+import net.sf.jguiraffe.resources.Message;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * <p>
+ * An abstract base class for action tasks that perform a desktop operation with
+ * the currently selected file.
+ * </p>
+ * <p>
+ * The tutorial application defines some actions for doing something with files
+ * which is implemented by the {@code Desktop} class new in Java 1.6 (e.g.
+ * opening a file or printing it). This abstract base class provides basic
+ * functionality for implementing such functionality. It is initialized with a
+ * reference to the main controller from which the currently selected file can
+ * be obtained. It also takes care for exception handling. A concrete subclass
+ * only has to implement the desired {@code Desktop} operation.
+ * </p>
+ *
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public abstract class AbstractDesktopTask implements Runnable
+{
+ /** The resource ID of the title of the error message box. */
+ private static final String RESID_ERR_TITLE = "task_errdesktop_title";
+
+ /** The resource ID of the text of the error message box. */
+ private static final String RESID_ERR_TEXT = "task_errdesktop_msg";
+
+ /** The logger. */
+ protected final Log log = LogFactory.getLog(getClass());
+
+ /** A reference to the main controller. */
+ private final MainWndController controller;
+
+ /**
+ * Creates a new instance of {@code AbstractDesktopTask} and sets the
+ * reference to the main controller.
+ *
+ * @param ctrl the main controller reference
+ */
+ protected AbstractDesktopTask(MainWndController ctrl)
+ {
+ controller = ctrl;
+ }
+
+ /**
+ * Returns a reference to the main controller.
+ *
+ * @return the main controller
+ */
+ public MainWndController getController()
+ {
+ return controller;
+ }
+
+ /**
+ * Returns the selected file.
+ *
+ * @return the selected file
+ */
+ public File getSelectedFile()
+ {
+ List<File> selection = controller.getSelectedFiles();
+ assert selection.size() == 1 : "Wrong number of selected files!";
+ return selection.get(0);
+ }
+
+ /**
+ * Executes this task. This implementation creates a new command for
+ * executing the desktop operation.
+ */
+ @Override
+ public void run()
+ {
+ getController().getApplication().execute(new DesktopCommand());
+ }
+
+ /**
+ * Performs the desired operation with the selected file. This method has to
+ * be implemented by concrete subclasses.
+ *
+ * @param desktop the {@code Desktop} instance
+ * @throws Exception if an error occurs
+ */
+ protected abstract void performDesktopOperation(Desktop desktop)
+ throws Exception;
+
+ /**
+ * A specialized command implementation for executing the desktop operation
+ * in a background thread.
+ */
+ private class DesktopCommand extends CommandBase
+ {
+ /**
+ * Executes this command. This implementation calls the
+ * {@code performDesktopOperation()} method.
+ */
+ @Override
+ public void execute() throws Exception
+ {
+ performDesktopOperation(Desktop.getDesktop());
+ }
+
+ /**
+ * Performs UI updates after executing the command. This implementation
+ * checks whether an error occurred. If this is the case, an exception
+ * message is displayed to the user.
+ */
+ @Override
+ protected void performGUIUpdate()
+ {
+ if (getException() != null)
+ {
+ log.error("Error on Desktop operation", getException());
+ getController()
+ .getApplication()
+ .getApplicationContext()
+ .messageBox(
+ new Message(null, RESID_ERR_TEXT,
+ getSelectedFile().getName()),
+ RESID_ERR_TITLE, MessageOutput.MESSAGE_ERROR,
+ MessageOutput.BTN_OK);
+ }
+ }
+ }
+}
Property changes on: trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/AbstractDesktopTask.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Author Id Revision HeadURL
Added: svn:eol-style
+ native
Added: trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/EditDesktopTask.java
===================================================================
--- trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/EditDesktopTask.java (rev 0)
+++ trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/EditDesktopTask.java 2010-08-26 18:43:51 UTC (rev 194)
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006-2010 The JGUIraffe Team.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License")
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.jguiraffe.examples.tutorial.mainwnd;
+
+import java.awt.Desktop;
+
+/**
+ * <p>
+ * A specialized action task for editing a selected file.
+ * </p>
+ *
+ * @author Oliver Heger
+ * @version $Id$
+ */
+public class EditDesktopTask extends AbstractDesktopTask
+{
+ /**
+ * Creates a new instance of {@code EditDesktopTask} and sets the main
+ * controller.
+ *
+ * @param ctrl the main controller
+ */
+ public EditDesktopTask(MainWndController ctrl)
+ {
+ super(ctrl);
+ }
+
+ /**
+ * Performs the desktop operation. This implementation asks the
+ * {@code Desktop} object to edit the selected file.
+ */
+ @Override
+ protected void performDesktopOperation(Desktop desktop) throws Exception
+ {
+ desktop.edit(getSelectedFile());
+ }
+}
Property changes on: trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/EditDesktopTask.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:keywords
+ Date Author Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/FileSizeTransformer.java
===================================================================
--- trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/FileSizeTransformer.java 2010-08-22 16:30:32 UTC (rev 193)
+++ trunk/examples/src/main/java/net/sf/jguiraffe/examples/tutorial/mainwnd/FileSizeTransformer.java 2010-08-26 18:43:51 UTC (rev 194)
@@ -22,22 +22,27 @@
import net.sf.jguiraffe.transform.TransformerContext;
/**
- * <p>A specialized transformer for formatting file sizes.</p>
- * <p>This transformer obtains the size of a file in kilobytes.</p>
+ * <p>
+ * A specialized transformer for formatting file sizes.
+ * </p>
+ * <p>
+ * This transformer obtains the size of a file in kilobytes.
+ * </p>
*
* @author Oliver Heger
* @version $Id$
*/
public class FileSizeTransformer implements Transformer
{
- /** Constant for the resource ID for the KB constant.*/
+ /** Constant for the resource ID for the KB constant. */
private static final String RES_KB = "trans_kb";
- /** The size of a kilobyte.*/
+ /** The size of a kilobyte. */
private static final long KB_SIZE = 1024;
/**
* Performs the transformation.
+ *
* @param o the object to transform
* @param ctx the transformer context
* @throws Exception if an error occurs
@@ -48,6 +53,8 @@
NumberFormat fmt = NumberFormat.getIntegerInstance(ctx.getLocale());
fmt.setGroupingUsed(true);
long sizeKb = (((Number) o).longValue() + KB_SIZE - 1) / KB_SIZE;
- return fmt.format(sizeKb) + ctx.getResourceManager().getText(ctx.getLocale(), null, RES_KB);
+ return fmt.format(sizeKb)
+ + ctx.getRes...
[truncated message content] |