Changeset 4170
- Timestamp:
- Mar 7, 2008, 2:07:10 PM (15 years ago)
- Location:
- branches/extensions
- Files:
-
- 8 added
- 1 deleted
- 27 edited
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/JspContext.java
r4168 r4170 32 32 33 33 import net.sf.basedb.core.SessionControl; 34 import net.sf.basedb.util.extensions.ActionFactory; 34 35 import net.sf.basedb.util.extensions.Context; 36 import net.sf.basedb.util.extensions.Extension; 37 import net.sf.basedb.util.extensions.RendererFactory; 35 38 36 39 /** 40 Context object for the web application. Instances of this class 41 are always used for passing context information to web extensions. 42 This means that it is always safe to cast the context to this 43 class in the {@link ActionFactory#prepareContext(Context, Extension)} 44 and {@link ActionFactory#getActions(Context, Extension)} methods 45 and other methods that has a context parameter. 46 47 <pre class="code"> 48 @Override 49 public boolean prepareContext(Context context, Extension extension) 50 { 51 JspContext jspContext = (JspContext)context; 52 jspContext.addStylesheet("/base/include/styles/mystylesheet.css"); 53 // Do other things 54 return true; 55 } 56 </pre> 57 58 <p> 59 This context exposes the underlying JSP {@link PageContext}, 60 which can be used to get information about the current request 61 among other things. Render factories usually needs access to 62 the response output stream, {@link #getOut()}, so that renderers 63 can write the generated HTML to the response. 37 64 38 65 @author nicklas … … 65 92 } 66 93 67 public void addScript(String path) 94 /** 95 Add an absolute reference to a script that should be included on the 96 generated page with a <code><script></code> tag. The 97 path must be an absolute path. 98 99 <p> 100 Note 1! This method must be called from the {@link 101 ActionFactory#prepareContext(Context, Extension)} or 102 {@link RendererFactory#prepareContext(Context, Extension)} 103 methods. Changes to the context after that will not be reflected 104 in the output. 105 106 <p> 107 Note 2! Not all extension points supports custom scripts. Check 108 the documentation for the extension point you are extending. 109 110 @param absolutePath The absolute path 111 */ 112 public void addScript(String absolutePath) 68 113 { 69 114 if (scripts == null) scripts = new HashSet<String>(); 70 scripts.add( path);115 scripts.add(absolutePath); 71 116 } 72 117 73 public void addStylesheet(String path) 118 /** 119 Add an absolute reference to a CSS stylesheet that should be included on the 120 generated page with a <code><link></code> tag. The 121 path must be the absolute path. 122 123 <p> 124 Note 1! This method must be called from the {@link 125 ActionFactory#prepareContext(Context, Extension)} or 126 {@link RendererFactory#prepareContext(Context, Extension)} 127 methods. Changes to the context after that will not be reflected 128 in the output. 129 130 <p> 131 Note 2! Not all extension points supports custom stylesheets. Check 132 the documentation for the extension point you are extending. 133 134 @param absolutePath The absolute path 135 */ 136 public void addStylesheet(String absolutePath) 74 137 { 75 138 if (stylesheets == null) stylesheets = new HashSet<String>(); 76 stylesheets.add( path);139 stylesheets.add(absolutePath); 77 140 } 141 78 142 79 public void writeScripts( String root)143 public void writeScripts() 80 144 throws IOException 81 145 { … … 84 148 { 85 149 out.write("<script language=\"JavaScript\" type=\"text/javascript\" src=\""); 86 out.write(root);87 150 out.write(script); 88 151 out.write("\"></script>\n"); -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/MevActionButtonFactory.java
r4168 r4170 27 27 import net.sf.basedb.clients.web.extensions.toolbar.ButtonBean; 28 28 import net.sf.basedb.core.BioAssaySet; 29 import net.sf.basedb.util.extensions.AbstractActionFactory;30 29 import net.sf.basedb.util.extensions.Context; 30 import net.sf.basedb.util.extensions.Extension; 31 import net.sf.basedb.util.extensions.xml.PathSetter; 32 import net.sf.basedb.util.extensions.xml.VariableSetter; 31 33 32 34 /** … … 37 39 */ 38 40 public class MevActionButtonFactory 39 extends Abstract ActionFactory<ButtonAction>41 extends AbstractJspActionFactory<ButtonAction> 40 42 { 41 43 … … 44 46 private String onClick; 45 47 46 public boolean prepareContext(Context context) 47 { 48 JspContext jspContext = (JspContext)context; 49 jspContext.addScript("mev_script.js"); 50 return true; 51 } 52 53 public ButtonAction[] getActions(Context context) 48 @Override 49 public ButtonAction[] getActions(Context context, Extension extension) 54 50 { 55 51 Object item = context.getCurrentItem(); … … 67 63 } 68 64 65 @PathSetter 66 @VariableSetter 69 67 public void setIcon(String icon) 70 68 { … … 75 73 this.title = title; 76 74 } 75 @VariableSetter 77 76 public void setOnClick(String onClick) 78 77 { -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/Settings.java
r4168 r4170 38 38 import net.sf.basedb.util.extensions.ExtensionPoint; 39 39 import net.sf.basedb.util.extensions.ExtensionsFilter; 40 import net.sf.basedb.util.extensions.Registry; 40 41 41 42 /** 42 43 Keeps settings for the extensions system. Settings 43 are kept in the file <code>WEB-INF/extensions/settings.xml</code> 44 44 are kept in the file <code>WEB-INF/extensions/settings.xml</code>. 45 <p> 46 47 Extension points and extensions can be disabled/enabled by 48 {@link #enableExtensionPoint(String, boolean)} and 49 {@link #enableExtension(String, boolean)}. 50 <p> 51 This class also implements the {@link ExtensionsFilter} 52 interface, and can be used on the 53 {@link Registry#useExtensions(net.sf.basedb.util.extensions.Context, ExtensionsFilter, String...)} 54 method. This means that disabling/enabling extensions and extension points 55 will immediately be visible in the web interface. 56 57 @author nicklas 58 @version 2.7 59 @base.modified $Date$ 45 60 */ 46 61 public class Settings … … 49 64 { 50 65 66 private boolean hasChanged; 51 67 private Presets presets; 52 68 private Preset settings; … … 71 87 this.disabledExtensionPoints = presets.getPreset("disabled-extension-points"); 72 88 this.disabledExtensions = presets.getPreset("disabled-extensions"); 89 hasChanged = false; 73 90 } 74 91 … … 100 117 { 101 118 disabledExtensions.setSetting(extensionId, enable ? null : "1"); 119 hasChanged = true; 102 120 } 103 121 … … 110 128 { 111 129 disabledExtensionPoints.setSetting(extensionPointId, enable ? null : "1"); 130 hasChanged = true; 112 131 } 113 132 133 /** 134 Save the settings to disk. If the settings has not been 135 changed the file is not written. 136 137 @throws IOException 138 */ 114 139 public synchronized void save() 115 140 throws IOException 116 141 { 142 if (!hasChanged) return; 117 143 OutputStream out = new FileOutputStream(filename); 118 144 presets.writeTo(out); 145 out.close(); 146 hasChanged = true; 119 147 } 120 148 } -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/WebExtensions.java
r4168 r4170 42 42 public static Settings SETTINGS; 43 43 44 public static String ROOT = "/extension"; 44 45 45 46 public static ExtensionsInvoker<?> useExtensions(JspContext context, String...extensionPoints) … … 48 49 } 49 50 50 public static String getRoot Url(Extension extension)51 public static String getRoot(Extension extension) 51 52 { 52 return "/extensions/" + extension.getId();53 return ROOT + "/extensions/" + extension.getId(); 53 54 } 54 55 56 /** 57 Convert a path to an absolute path seen from the web 58 servers perspective. Here are the rules: 59 <ol> 60 <li>If <code>path</code> starts with '/', the path is relative to 61 the BASE application root directory, which is added to 62 the beginning of the path, for example, 63 <code>/images/copy.gif --> /base/images/copy.gif</code> 64 65 <li>If <code>path</code> stars with '~', the path is relative to 66 the extensions home directory. The home directory of an extension 67 is normally located in the <code>/extensions</code> directory 68 with a name based on the JAR file the extension is located in. 69 For example, 70 <code>~/images/tmev.png --> /base/extensions/net.sf.basedb.mev/images/tmev.png</code>. 71 72 <li>Otherwise, the <code>path</code> is returned unmodified. 73 </ol> 74 75 @param path The path to convert to an absolute path 76 @param extension The extension that is requesting the path 77 conversion 78 @return The absolute path 79 */ 55 80 public static String makeAbsolutePath(String path, Extension extension) 56 81 { 57 if (path != null && path.startsWith("~"))82 if (path != null) 58 83 { 59 path = getRootUrl(extension) + path.substring(1); 84 if (path.startsWith("/")) 85 { 86 path = ROOT + path; 87 } 88 else if (path.startsWith("~")) 89 { 90 path = getRoot(extension) + path.substring(1); 91 } 60 92 } 61 93 return path; -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/menu/FixedMenuItemFactory.java
r4168 r4170 24 24 package net.sf.basedb.clients.web.extensions.menu; 25 25 26 import net.sf.basedb.clients.web.extensions.AbstractJspActionFactory; 26 27 import net.sf.basedb.util.Values; 27 import net.sf.basedb.util.extensions.ActionFactory;28 28 import net.sf.basedb.util.extensions.Context; 29 import net.sf.basedb.util.extensions.Extension; 30 import net.sf.basedb.util.extensions.xml.PathSetter; 31 import net.sf.basedb.util.extensions.xml.VariableSetter; 29 32 30 33 /** 31 34 A simple implementation of a menu item action factory that 32 35 creates the same fixed menu item for all users 33 not using any context information. 36 not using any context information. 34 37 <p> 35 38 The menu is by default a regular menuitem and is both … … 37 40 the properties. Changes to the properties are immediately 38 41 visible in the menu items returned from the {@link #getActions(Context)} 39 method. 42 method. 40 43 41 44 @author nicklas … … 44 47 */ 45 48 public class FixedMenuItemFactory 46 implements ActionFactory<MenuItemAction>, MenuItemAction47 49 extends AbstractJspActionFactory<MenuItemAction> 50 implements MenuItemAction 48 51 { 49 52 … … 75 78 */ 76 79 @Override 77 public MenuItemAction[] getActions(Context context) 80 public MenuItemAction[] getActions(Context context, 81 Extension<? super MenuItemAction> extension) 78 82 { 79 83 return actions; 80 }81 82 @Override83 public boolean prepareContext(Context context)84 {85 return true;86 84 } 87 85 // ------------------------------------ … … 140 138 // ------------------------------------ 141 139 140 /* 141 Setter methods that are called when the factory is 142 initialised. 143 */ 144 @VariableSetter 145 @PathSetter 142 146 public void setIcon(String icon) 143 147 { … … 145 149 } 146 150 151 @VariableSetter 147 152 public void setOnClick(String onClick) 148 153 { … … 194 199 this.type = MenuType.valueOf(type); 195 200 } 201 // ------------------------------------ 196 202 197 203 @Override … … 208 214 sb.append("; visible=" + visible); 209 215 sb.append("; enabled=" + enabled); 216 sb.append(super.toString()); 210 217 return sb.toString(); 211 218 } -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/menu/MenuItemAction.java
r4168 r4170 57 57 58 58 /** 59 Get a reference to an image that will be displayed in the menu.59 Get an absolute reference to an image that will be displayed in the menu. 60 60 It is recommended that the image is 9 pixels wide and 12 pixels high to 61 line up with the icons used by the BASE core menus. If the image 62 URL starts with: 63 <ul> 64 <li><b>/</b> It is interpreted as relative to the 65 root directory of the BASE application (normally, /base) 66 <li><b>~</b> It is interpreted as relative to the resources directory 67 for the current extension (normally, /base/extensions/ID) 68 <li>Otherwise it is interpreted as relative to the 'images' 69 subdirectory (/base/images). 70 </ul> 61 line up with the icons used by the BASE core menus. 71 62 72 63 @return A reference to an image, or null if no image should … … 119 110 Menu.openUrl(getRoot()+'views/reporters/index.jsp?ID='+getSessionId()); 120 111 </pre> 121 112 113 Another possibility that works for the root path is to 114 use a factory that has enabled variable substitution. In this 115 case you can use: 116 117 <pre class="code"> 118 Menu.openUrl('$ROOT$/views/reporters/index.jsp?ID='+getSessionId()); 119 </pre> 120 122 121 <li>To open a popup window use: 123 122 <code>Main.openPopup(url, windowName, width, height, options)</code> … … 131 130 documentation for the <code>window.open()</code> javascript function 132 131 for valid syntax. 133 134 132 </ul> 135 133 -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/menu/PermissionMenuItemFactory.java
r4168 r4170 24 24 package net.sf.basedb.clients.web.extensions.menu; 25 25 26 import net.sf.basedb.clients.web.extensions.AbstractJspActionFactory; 26 27 import net.sf.basedb.clients.web.extensions.menu.MenuItemAction.MenuType; 27 28 import net.sf.basedb.core.Item; 28 29 import net.sf.basedb.core.Permission; 29 30 import net.sf.basedb.core.SessionControl; 30 import net.sf.basedb.util.extensions.ActionFactory;31 31 import net.sf.basedb.util.extensions.Context; 32 import net.sf.basedb.util.extensions.Extension; 33 import net.sf.basedb.util.extensions.xml.PathSetter; 34 import net.sf.basedb.util.extensions.xml.VariableSetter; 32 35 33 36 /** … … 60 63 */ 61 64 public class PermissionMenuItemFactory 62 implementsActionFactory<MenuItemAction>65 extends AbstractJspActionFactory<MenuItemAction> 63 66 { 64 67 … … 98 101 */ 99 102 @Override 100 public MenuItemAction[] getActions(Context context )103 public MenuItemAction[] getActions(Context context, Extension<? super MenuItemAction> extension) 101 104 { 102 105 SessionControl sc = context.getSessionControl(); … … 120 123 } 121 124 return new MenuItemAction[] { action }; 122 123 125 } 124 126 125 127 @Override 126 public boolean prepareContext(Context context )128 public boolean prepareContext(Context context, Extension<? super MenuItemAction> extension) 127 129 { 128 130 SessionControl sc = context.getSessionControl(); 129 return hasPermission(sc, visiblePermission); 131 boolean isEnabled = hasPermission(sc, visiblePermission); 132 return isEnabled && super.prepareContext(context, extension); 130 133 } 131 134 // ------------------------------------ … … 163 166 Set the icon to use when the menu is enabled. 164 167 */ 168 @VariableSetter 169 @PathSetter 165 170 public void setEnabledIcon(String icon) 166 171 { … … 170 175 Set the icon to use when the menu is disabled. 171 176 */ 177 @VariableSetter 178 @PathSetter 172 179 public void setDisabledIcon(String icon) 173 180 { … … 177 184 Set the icon to use in all cases. 178 185 */ 186 @VariableSetter 187 @PathSetter 179 188 public void setIcon(String icon) 180 189 { … … 186 195 Set the javascript action to call when the menu is clicked. 187 196 */ 197 @VariableSetter 188 198 public void setOnClick(String onClick) 189 199 { -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/toolbar/CompactButtonRendererFactory.java
r4168 r4170 26 26 import net.sf.basedb.clients.web.extensions.JspContext; 27 27 import net.sf.basedb.util.extensions.Context; 28 import net.sf.basedb.util.extensions.Extension; 28 29 import net.sf.basedb.util.extensions.RendererFactory; 29 30 … … 38 39 { 39 40 41 public void prepareContext(Context context, Extension extension) 42 { 43 44 } 40 45 41 public CompactButtonRenderer getRenderer(Context context )46 public CompactButtonRenderer getRenderer(Context context, Extension extension) 42 47 { 43 48 return new CompactButtonRenderer((JspContext)context); -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/extensions/toolbar/FixedButtonFactory.java
r4168 r4170 24 24 package net.sf.basedb.clients.web.extensions.toolbar; 25 25 26 import net.sf.basedb.clients.web.extensions.AbstractJspActionFactory; 26 27 import net.sf.basedb.util.Values; 27 import net.sf.basedb.util.extensions.ActionFactory;28 28 import net.sf.basedb.util.extensions.Context; 29 import net.sf.basedb.util.extensions.Extension; 30 import net.sf.basedb.util.extensions.xml.PathSetter; 31 import net.sf.basedb.util.extensions.xml.VariableSetter; 29 32 30 33 /** … … 33 36 not using any context information. 34 37 <p> 35 The button is by default both 36 visible and enabled. Use the setter method to change 37 the properties. Changes to the properties are immediately 38 The button is by default both visible and enabled. Use the setter 39 method to change the properties. Changes to the properties are immediately 38 40 visible in the menu items returned from the {@link #getActions(Context)} 39 41 method. 42 <p> 43 If the extension point supports scripts and stylesheets, use the 44 {@link #setScript(String)} and {@link #setStylesheet(String)} methods. 45 Each call to these methods will add the the argument to a set. Use 46 the {@link #getScripts()} and {@link #getStylesheets()} methods to gain 47 access to the sets, for example, to remove added items. 40 48 41 49 @author nicklas … … 44 52 */ 45 53 public class FixedButtonFactory 46 implements ActionFactory<ButtonAction>, ButtonAction 54 extends AbstractJspActionFactory<ButtonAction> 55 implements ButtonAction 47 56 48 57 { … … 75 84 */ 76 85 @Override 77 public ButtonAction[] getActions(Context context )86 public ButtonAction[] getActions(Context context, Extension extension) 78 87 { 79 88 return actions; 80 }81 82 @Override83 public boolean prepareContext(Context context)84 {85 return true;86 89 } 87 90 // ------------------------------------ … … 151 154 } 152 155 156 @VariableSetter 157 @PathSetter 153 158 public void setIcon(String icon) 154 159 { … … 161 166 } 162 167 168 @VariableSetter 163 169 public void setOnClick(String onClick) 164 170 { … … 201 207 } 202 208 203 204 209 @Override 205 210 public String toString() … … 216 221 sb.append("; visible=" + visible); 217 222 sb.append("; enabled=" + enabled); 223 if (getScripts() != null) sb.append("; scripts=" + getScripts()); 224 if (getStylesheets() != null) sb.append("; stylesheets=" + getStylesheets()); 218 225 return sb.toString(); 219 226 } -
branches/extensions/src/clients/web/net/sf/basedb/clients/web/servlet/ExtensionsServlet.java
r4168 r4170 39 39 import net.sf.basedb.util.RegexpFileFilter; 40 40 import net.sf.basedb.util.extensions.Registry; 41 import net.sf.basedb.util.extensions.XmlLoader; 41 import net.sf.basedb.util.extensions.xml.PathConverter; 42 import net.sf.basedb.util.extensions.xml.VariableConverter; 43 import net.sf.basedb.util.extensions.xml.XmlLoader; 42 44 43 45 /** … … 93 95 { 94 96 XmlLoader loader = new XmlLoader(); 97 VariableConverter variableConverter = new VariableConverter(); 98 variableConverter.setVariable("ROOT", "/extensions"); 99 variableConverter.setVariable("HOME", extensionsPath); 100 loader.addValueConverter(variableConverter); 101 102 PathConverter pathConverter = new PathConverter("/extensions", extensionsPath); 103 loader.addValueConverter(pathConverter); 104 95 105 // Load core extension points 96 106 URL coreExtensionPoints = … … 112 122 { 113 123 if (xmlFile.getName().equals("settings.xml")) continue; 124 pathConverter.setHome("/extensions/extensions/" + xmlFile.getName()); 114 125 try 115 126 { -
branches/extensions/src/core/net/sf/basedb/util/extensions/AboutBean.java
r4163 r4170 28 28 /** 29 29 An implementation of the {@link About} interface, which 30 complements all methods with setter methods.30 complements all getter methods with setter methods. 31 31 32 32 @author nicklas -
branches/extensions/src/core/net/sf/basedb/util/extensions/ActionFactory.java
r4163 r4170 24 24 package net.sf.basedb.util.extensions; 25 25 26 import net.sf.basedb.util.extensions.xml.XmlLoader; 27 26 28 /** 27 An action factory is an object which knows how to create actions. 28 An action factory is defined by an {@link Extension}. The implementation 29 must be thread safe since only a single instance of the factory exists 30 to serve all requests. 29 An action factory is an object which knows how to create 30 {@link Action}:s. Action factories are part of an extension 31 (see {@link Extension#getActionFactory()}). 32 33 <p> 34 Action factory implementations must be thread-safe, since a 35 single instance of the factory may have to serve multiple requests 36 at the same time. 37 38 <p> 39 Note 1! A single factory instance may be used by more than one 40 extension. This is at the control of the client application. 41 42 <p> 43 Note 2! The BASE web-client uses the {@link XmlLoader} to 44 define extensions. The <code>XmlLoader</code> always create a 45 separate factory instance for each extension. The <code>XmlLoader</code> 46 also requires that the factories has a public no-argument constructor. 31 47 32 48 @author nicklas … … 38 54 39 55 /** 40 This method is called once for each request and should be used 41 by the factory to decide if the extension should be enabled or not and 42 to initialise the context with, for example, resources that the 43 actions may need. In the case of the web client, this may for 44 example, be any scripts and/or style sheet files that is needed 45 by the extension. 56 This method is called once for each request/use of an 57 extension and have two purposes: 46 58 47 @param context The current context 48 @return TRUE if the extension should be enabled, FALSE if the extension should 49 be disabled 59 <ul> 60 <li>The factory should decide if the extension should be enabled or 61 not. For example, the factory may check the permissions of the 62 logged in user and determine that they are inadequate. The boolean 63 return value determines if the extension is enabled or disabled. 64 65 <li>Initialise the context with resources that the actions may need. 66 With the BASE web-client this means that it is possible to 67 add scripts or stylesheets that is needed by the extension. 68 See {@link JspContext}. 69 </ul> 70 71 @param context The current context to prepare 72 @param extension The extension to use 73 @return TRUE if the extension should be enabled, 74 FALSE if the extension should be disabled 50 75 */ 51 public boolean prepareContext(Context context );76 public boolean prepareContext(Context context, Extension<? super A> extension); 52 77 53 78 /** … … 61 86 62 87 @param context The current context 88 @param extension The extension to create actions for 63 89 @return An array of actions that should be added to the extension point. 64 90 Returns null or an empty array if there are no actions in the current context. 65 91 */ 66 public A[] getActions(Context context );92 public A[] getActions(Context context, Extension<? super A> extension); 67 93 68 94 } -
branches/extensions/src/core/net/sf/basedb/util/extensions/ActionIterator.java
r4168 r4170 1 /** 2 $Id: $ 3 4 Copyright (C) Authors contributing to this file. 5 6 This file is part of BASE - BioArray Software Environment. 7 Available at http://base.thep.lu.se/ 8 9 BASE is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License 11 as published by the Free Software Foundation; either version 2 12 of the License, or (at your option) any later version. 13 14 BASE is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place - Suite 330, 22 Boston, MA 02111-1307, USA. 23 */ 1 24 package net.sf.basedb.util.extensions; 2 25 … … 10 33 11 34 /** 12 Iterator for iteratoring over all actions created by 13 extensions by {@link ExtensionsInvoker#i 14 over all actions. 35 Iterator for iterating over all actions that <b>will be 36 created</b> by extensions after a call to {@link 37 Registry#useExtensions(Context, ExtensionsFilter, String...)}. 38 That method returns an {@link ExtensionsInvoker} object which 39 in it's turn uses this iterator. 40 41 <p> 42 Note the phrase "will be created" above. The actions 43 are created on demand as this iterator moves on the 44 next item. This happens in the {@link #hasNext()} method, which, 45 for each extension, calls {@link Extension#getActionFactory()} 46 and then {@link ActionFactory#getActions(Context, Extension)}. 47 48 <p> 49 The actions returned from the extensions are piled up in an 50 internal buffer that the {@link #next()} method pick items from. 51 When the buffer is empty the iterator moves on to the actions from 52 next extension until there are no more extensions and the action 53 buffer is empty. 54 55 @author nicklas 56 @version 2.7 57 @base.modified $Date$ 15 58 */ 16 59 public class ActionIterator<A extends Action> … … 33 76 34 77 // The renderer for the current action 35 private Renderer< A> currentRenderer;78 private Renderer<? super A> currentRenderer; 36 79 37 80 // Cache for created renderers 38 private Map<Object, Renderer< A>> rendererCache;81 private Map<Object, Renderer<? super A>> rendererCache; 39 82 40 83 // Boolean flags to indicate if we have a next element and if … … 49 92 this.iterator = iterator; 50 93 this.checkNext = true; 51 this.rendererCache = new IdentityHashMap<Object, Renderer< A>>();94 this.rendererCache = new IdentityHashMap<Object, Renderer<? super A>>(); 52 95 } 53 96 … … 78 121 currentExtension = iterator.next(); 79 122 // Get the actions for the extension 80 actions = currentExtension.getActionFactory().getActions(context );123 actions = currentExtension.getActionFactory().getActions(context, currentExtension); 81 124 if (actions != null && actions.length > 0) 82 125 { … … 110 153 Get the extension that created the current action. 111 154 */ 112 public Extension< A> getExtension()155 public Extension<? extends A> getExtension() 113 156 { 114 157 return currentExtension; … … 118 161 Gets the renderer for the current action. 119 162 */ 120 Renderer< A> getRenderer()163 Renderer<? super A> getRenderer() 121 164 { 122 165 if (currentRenderer == null) 123 166 { 124 RegisteredExtensionPoint< A> ep = currentExtension.getExtensionPoint();125 RendererFactory< A> rf = currentExtension.getRendererFactory();167 RegisteredExtensionPoint<? super A> ep = currentExtension.getExtensionPoint(); 168 RendererFactory<? super A> rf = currentExtension.getRendererFactory(); 126 169 if (ep.allowRendererOverride() && rf != null) 127 170 { 128 171 // Use the extension's renderer factory if it is 129 172 // allowed and if one is provided 130 currentRenderer = rf.getRenderer(context );173 currentRenderer = rf.getRenderer(context, currentExtension); 131 174 } 132 175 else … … 137 180 if (currentRenderer == null) 138 181 { 139 currentRenderer = ep.getRendererFactory().getRenderer(context );182 currentRenderer = ep.getRendererFactory().getRenderer(context, currentExtension); 140 183 rendererCache.put(ep, currentRenderer); 141 184 } -
branches/extensions/src/core/net/sf/basedb/util/extensions/Context.java
r4168 r4170 41 41 The current context is passed to an {@link ActionFactory} twice, first 42 42 to check if an extension should be enabled or not 43 with the {@link ActionFactory#prepareContext(Context )}43 with the {@link ActionFactory#prepareContext(Context, Extension)} 44 44 method. This method also allows an extension to write 45 45 back information to the context. This may, for example, … … 50 50 <p> 51 51 The second time is when calling the {@link 52 ActionFactory#getActions(Context )} method. This method can52 ActionFactory#getActions(Context, Extension)} method. This method can 53 53 be called multiple times. For example, if an extension point 54 54 is in a list context, the <code>getActions</code> method may … … 73 73 74 74 /** 75 Create a new context. 75 Create a new context with a session. The session is final and can't 76 be replaced. 76 77 @param sc The current session 77 78 */ … … 82 83 83 84 /** 84 Create a new context. 85 Create a new context with a session and item. The session is final and 86 can't be replaced. Use {@link #setCurrentItem(Object)} to change the item. 87 85 88 @param sc The current session 86 89 @param item The current item -
branches/extensions/src/core/net/sf/basedb/util/extensions/DefaultFilter.java
r4168 r4170 46 46 @see Extension#getIndex() 47 47 */ 48 public static final Comparator<Extension > INDEX_COMPARATOR =49 new Comparator<Extension >()48 public static final Comparator<Extension<?>> INDEX_COMPARATOR = 49 new Comparator<Extension<?>>() 50 50 { 51 51 @Override 52 public int compare(Extension o1, Extensiono2)52 public int compare(Extension<?> o1, Extension<?> o2) 53 53 { 54 54 return Float.compare(o1.getIndex(), o2.getIndex()); … … 67 67 */ 68 68 @Override 69 public boolean isEnabled(ExtensionPoint extensionPoint)69 public boolean isEnabled(ExtensionPoint<?> extensionPoint) 70 70 { 71 71 return true; … … 73 73 74 74 @Override 75 public boolean isEnabled(Extension extension)75 public boolean isEnabled(Extension<?> extension) 76 76 { 77 77 return true; … … 79 79 80 80 @Override 81 public void sort(List<? extends Extension > extensions)81 public void sort(List<? extends Extension<?>> extensions) 82 82 { 83 83 Collections.sort(extensions, INDEX_COMPARATOR); -
branches/extensions/src/core/net/sf/basedb/util/extensions/Extension.java
r4163 r4170 25 25 26 26 import net.sf.basedb.core.plugin.About; 27 import net.sf.basedb.util.extensions.xml.XmlLoader; 27 28 28 29 /** … … 42 43 Extensions can, for example, be created: 43 44 <ul> 44 <li>Programmatically, using {@link ExtensionBean} object45 <li>Programmatically, using an {@link ExtensionBean} object. 45 46 <li>Loaded from extension definition XML files using a {@link XmlLoader}. 46 <li>Or, in any other way by providing a custom implementation of this interface 47 <li>Or, in any other way by providing a custom implementation of this interface. 47 48 </ul> 48 49 … … 73 74 74 75 /** 75 The extensions in an extension point are ordered by their76 The extensions in an extension point are by default ordered by their 76 77 index value. Extensions with a low value are ordered before 77 extensions with a high value. 78 extensions with a high value. The ordering may be overridden by providing 79 an external {@link ExtensionsFilter} implementation. 78 80 @return The index value 79 81 */ … … 92 94 objects of the same class or a subclass as the {@link ExtensionPoint#getActionClass()} 93 95 method of the extended extension point returns. 94 @return An action factory 96 @return An action factory (required) 95 97 */ 96 public ActionFactory< A> getActionFactory();98 public ActionFactory<? extends A> getActionFactory(); 97 99 98 100 /** … … 103 105 @see ExtensionPoint#allowRendererOverride() 104 106 */ 105 public RendererFactory< A> getRendererFactory();107 public RendererFactory<? super A> getRendererFactory(); 106 108 107 109 } -
branches/extensions/src/core/net/sf/basedb/util/extensions/ExtensionBean.java
r4163 r4170 41 41 private String id; 42 42 private String extensionPoint; 43 private ActionFactory< A> actionFactory;44 private RendererFactory< A> rendererFactory;43 private ActionFactory<? extends A> actionFactory; 44 private RendererFactory<? super A> rendererFactory; 45 45 private About about; 46 46 private float index; … … 63 63 float position, 64 64 About about, 65 ActionFactory< A> actionFactory,66 RendererFactory< A> rendererFactory)65 ActionFactory<? extends A> actionFactory, 66 RendererFactory<? super A> rendererFactory) 67 67 { 68 68 this.id = id; … … 105 105 106 106 @Override 107 public ActionFactory< A> getActionFactory()107 public ActionFactory<? extends A> getActionFactory() 108 108 { 109 109 return actionFactory; 110 110 } 111 public void setActionFactory(ActionFactory< A> actionFactory)111 public void setActionFactory(ActionFactory<? extends A> actionFactory) 112 112 { 113 113 this.actionFactory = actionFactory; … … 115 115 116 116 @Override 117 public RendererFactory< A> getRendererFactory()117 public RendererFactory<? super A> getRendererFactory() 118 118 { 119 119 return rendererFactory; 120 120 } 121 public void setRendererFactory(RendererFactory< A> rendererFactory)121 public void setRendererFactory(RendererFactory<? super A> rendererFactory) 122 122 { 123 123 this.rendererFactory = rendererFactory; -
branches/extensions/src/core/net/sf/basedb/util/extensions/ExtensionPoint.java
r4168 r4170 24 24 package net.sf.basedb.util.extensions; 25 25 26 import net.sf.basedb.util.extensions.xml.XmlLoader; 27 26 28 27 29 /** … … 48 50 an extension point are registered in the same registry with 49 51 {@link Registry#registerExtension(Extension)}. To load and use all 50 registered extensions use {@link Registry#getExtensions(String, Context)}. 52 registered extensions use 53 {@link Registry#useExtensions(Context, ExtensionsFilter, String...)}. 51 54 52 55 @author nicklas … … 88 91 extension point must provide an {@link ActionFactory} that is capable 89 92 of creating instances of the specified class. 93 90 94 @return The class of the actions that can be used on this extension point 95 (required) 91 96 */ 92 97 public Class<A> getActionClass(); … … 100 105 @return A renderer factory or null 101 106 */ 102 public RendererFactory< A> getRendererFactory();107 public RendererFactory<? super A> getRendererFactory(); 103 108 104 109 /** -
branches/extensions/src/core/net/sf/basedb/util/extensions/ExtensionPointBean.java
r4168 r4170 41 41 private String description; 42 42 private Class<A> actionClass; 43 private RendererFactory< A> rendererFactory;43 private RendererFactory<? super A> rendererFactory; 44 44 private boolean allowRendererOverride; 45 45 … … 114 114 115 115 @Override 116 public RendererFactory< A> getRendererFactory()116 public RendererFactory<? super A> getRendererFactory() 117 117 { 118 118 return rendererFactory; 119 119 } 120 public void setRendererFactory(RendererFactory< A> rendererFactory)120 public void setRendererFactory(RendererFactory<? super A> rendererFactory) 121 121 { 122 122 this.rendererFactory = rendererFactory; -
branches/extensions/src/core/net/sf/basedb/util/extensions/ExtensionsFilter.java
r4168 r4170 45 45 it is disabled 46 46 */ 47 public boolean isEnabled(ExtensionPoint extensionPoint);47 public boolean isEnabled(ExtensionPoint<?> extensionPoint); 48 48 49 49 /** … … 53 53 it is disabled 54 54 */ 55 public boolean isEnabled(Extension extension);55 public boolean isEnabled(Extension<?> extension); 56 56 57 57 /** … … 59 59 @param extensions The list of extensions to sort 60 60 */ 61 public void sort(List<? extends Extension > extensions);61 public void sort(List<? extends Extension<?>> extensions); 62 62 63 63 } -
branches/extensions/src/core/net/sf/basedb/util/extensions/ExtensionsInvoker.java
r4168 r4170 32 32 /** 33 33 Object of this class handles a single invokation of the extensions 34 for one or several extension points. Call {@link Registry#useExtensions(Context, String...)} 34 for one or several extension points. Call 35 {@link Registry#useExtensions(Context, ExtensionsFilter, String...)} 35 36 to create an invoker object. With this object you can 36 37 {@link #iterate()} over all actions created by the extensions, or … … 43 44 Since the registration of rendering factories are optional, the 44 45 <code>renderDefault()</code> method only works with extensions that have 45 done so. 46 done so. If an action can't be associated with a renderer, an exception 47 is thrown. 46 48 47 49 <p> 48 50 If there is no default rendering factory or if you want to override the default 49 renderer, you can use the {@link #render(Renderer)} method. This will always50 work, even if an extension point has specified that the rendering factory51 can't be overridden (this only applies to extensions).51 renderer, you can use the {@link #render(Renderer)} method. This will force 52 the use of the specified renderer for all extensions, ignoring all renderers 53 set by extension points or extensions. 52 54 53 55 @author nicklas … … 62 64 private RendererFactory<A> currentRenderFactory; 63 65 66 /** 67 Creates a new invoker object. 68 */ 64 69 ExtensionsInvoker(Collection<RegisteredExtension<A>> extensions, Context context) 65 70 { … … 92 97 { 93 98 A action = it.next(); 94 Renderer< A> renderer = it.getRenderer();99 Renderer<? super A> renderer = it.getRenderer(); 95 100 if (renderer == null) 96 101 { -
branches/extensions/src/core/net/sf/basedb/util/extensions/Registry.java
r4168 r4170 37 37 38 38 import net.sf.basedb.core.plugin.About; 39 import net.sf.basedb.util.extensions.xml.XmlLoader; 39 40 40 41 /** … … 43 44 be created programmatically using the {@link ExtensionPointBean} 44 45 and {@link ExtensionBean} implementations, or loaded from 45 an extensions definition XMLfile with the {@link XmlLoader}46 an XML extension definition file with the {@link XmlLoader} 46 47 class. Applications may provide other means of creating and 47 48 registering extensions and extensions points. … … 314 315 depending on the application, some information about what it about to 315 316 happen. For example, that we are going to display a list of samples. 317 316 318 <p> 317 319 Each extension that has been registered with the extension points will 318 320 get a chance to check the context object and to further initialise it 319 321 with extension-dependent information. This is a task for the 320 {@link ActionFactory#prepareContext(Context )} method. If this method returns321 false the extension will not be included in the invoker. Extensions322 {@link ActionFactory#prepareContext(Context, Extension)} method. If this method 323 returns false the extension will not be included in the invoker. Extensions 322 324 may for example use this to check if the logged in user has enough permissions 323 325 to be able to use the extension. 326 327 <p> 328 If the extension points and/or extensions also provide renderer factories, 329 the {@link RendererFactory#prepareContext(Context, Extension)} is called. 330 For renderer factories that are attached to extension points the method 331 is only called if at least one enabled extension exists. If the method is 332 called, it is only called once with a null argument for the extension. 333 Renderer factories that are attached to extensions are called once for each 334 extension, but only if the extension point allows it. 335 See {@link ExtensionPoint#allowRendererOverride()}. 324 336 325 337 <p> … … 329 341 330 342 @param context Information about the current context 331 @param filter A filter object that can be used to filter out343 @param filter A filter object that can be used to filter out 332 344 disabled extensions and sort the extensions in a particular order. 333 345 If this value is null, no extensions are filtered out and they 334 346 are sorted according to their {@link Extension#getIndex()} value 335 @param extensionPoints An array of extension point ID:s to get347 @param extensionPoints An array of extension point ID:s to get 336 348 extension for. In most cases the extension points should 337 349 require the same action class but this is not required … … 340 352 */ 341 353 @SuppressWarnings("unchecked") 342 public ExtensionsInvoker<?> useExtensions(Context context, ExtensionsFilter filter, String... extensionPoints) 354 public ExtensionsInvoker<?> useExtensions(Context context, ExtensionsFilter filter, 355 String... extensionPoints) 343 356 { 344 357 if (filter == null) filter = DEFAULT_FILTER; … … 350 363 if (rep != null && filter.isEnabled(rep)) 351 364 { 365 boolean allowRenderOverride = rep.allowRendererOverride(); 366 int enabledExtensions = 0; 352 367 for (RegisteredExtension<Action> ext : rep.getExtensions()) 353 368 { 354 if (filter.isEnabled(ext) && ext.getActionFactory().prepareContext(context ))369 if (filter.isEnabled(ext) && ext.getActionFactory().prepareContext(context, ext)) 355 370 { 356 371 use.add(ext); 372 enabledExtensions++; 373 if (allowRenderOverride) 374 { 375 RendererFactory<? super Action> factory = ext.getRendererFactory(); 376 if (factory != null) factory.prepareContext(context, ext); 377 } 357 378 } 379 } 380 RendererFactory<? super Action> factory = rep.getRendererFactory(); 381 if (enabledExtensions > 0 && factory != null) 382 { 383 factory.prepareContext(context, null); 358 384 } 359 385 } … … 380 406 private String name; 381 407 private String description; 382 private RendererFactory< A> rendererFactory;408 private RendererFactory<? super A> rendererFactory; 383 409 private boolean allowRendererOverride; 384 410 … … 429 455 430 456 @Override 431 public RendererFactory< A> getRendererFactory()457 public RendererFactory<? super A> getRendererFactory() 432 458 { 433 459 return rendererFactory; … … 490 516 { 491 517 492 private final RegisteredExtensionPoint< A> rep;518 private final RegisteredExtensionPoint<? super A> rep; 493 519 private final String id; 494 520 private final String extensionPoint; 495 521 private RegisteredAbout about; 496 522 private float index; 497 private ActionFactory< A> actionFactory;498 private RendererFactory< A> rendererFactory;523 private ActionFactory<? extends A> actionFactory; 524 private RendererFactory<? super A> rendererFactory; 499 525 500 526 /** … … 502 528 information from the parameter. 503 529 */ 504 RegisteredExtension(Extension<A> extension, RegisteredExtensionPoint< A> rep)530 RegisteredExtension(Extension<A> extension, RegisteredExtensionPoint<? super A> rep) 505 531 { 506 532 this.rep = rep; 507 533 this.id = extension.getId(); 508 534 this.extensionPoint = extension.getExtends(); 509 this.index = extension.getIndex(); 510 this.about = extension.getAbout() == null ? 511 null : new RegisteredAbout(extension.getAbout()); 512 this.actionFactory = extension.getActionFactory(); 513 this.rendererFactory = extension.getRendererFactory(); 535 update(extension); 514 536 } 515 537 … … 537 559 538 560 @Override 539 public ActionFactory< A> getActionFactory()561 public ActionFactory<? extends A> getActionFactory() 540 562 { 541 563 return actionFactory; … … 543 565 544 566 @Override 545 public RendererFactory< A> getRendererFactory()567 public RendererFactory<? super A> getRendererFactory() 546 568 { 547 569 return rendererFactory; … … 589 611 Get the extension point this extension is registered with. 590 612 */ 591 RegisteredExtensionPoint< A> getExtensionPoint()613 RegisteredExtensionPoint<? super A> getExtensionPoint() 592 614 { 593 615 return rep; -
branches/extensions/src/core/net/sf/basedb/util/extensions/RendererFactory.java
r4163 r4170 24 24 package net.sf.basedb.util.extensions; 25 25 26 import net.sf.basedb.util.extensions.xml.XmlLoader; 27 26 28 /** 27 29 A renderer factory is a factory that can create {@link Renderer} … … 30 32 extension point an extension may provide it's own factory 31 33 implementation ({@link Extension#getRendererFactory()}. 32 The factory implementation must be thread safe since only a 33 single instance of the factory exists to serve all requests. 34 35 <p> 36 Renderer factory implementations must be thread-safe, since a 37 single instance of the factory may have to serve multiple requests 38 at the same time. 39 40 <p> 41 Note 1! A single factory instance may be used by more than one 42 extension/extension point. This is at the control of the client application. 43 44 <p> 45 Note 2! The BASE web-client uses the {@link XmlLoader} to 46 define extensions. The <code>XmlLoader</code> always create a 47 separate factory instance for each extension/extension point. 48 The <code>XmlLoader</code> also requires that the factories has 49 a public no-argument constructor. 34 50 35 51 @author nicklas … … 41 57 42 58 /** 59 This method is called once for each request/use of an 60 extension and should be used by a factory to initialise the context 61 with resources that the actions may need. With the BASE web-client 62 this means that it is possible to add scripts or stylesheets that 63 is needed by the extension. See {@link JspContext}. 64 65 <p> 66 Note! This method has no return as opposed to 67 {@link ActionFactory#prepareContext(Context, Extension). The 68 simple reason is that once we get to the point of rendering it 69 is already known that the extension is enabled. 70 71 @param context The current context to prepare 72 @param extension The extension to use, or null if this 73 factory is used from an extension point 74 */ 75 public void prepareContext(Context context, Extension<? extends A> extension); 76 77 /** 43 78 Get a renderer for a given context. This method may 44 79 create a new instance or use an existing instance. If … … 47 82 48 83 @param context The current context 84 @param extension The extension to create a renderer for 49 85 @return A renderer instance 50 86 */ 51 public Renderer< A> getRenderer(Context context);87 public Renderer<? super A> getRenderer(Context context, Extension<? extends A> extension); 52 88 53 89 } -
branches/extensions/src/core/net/sf/basedb/util/extensions/xml/XmlLoader.java
r4168 r4170 22 22 Boston, MA 02111-1307, USA. 23 23 */ 24 package net.sf.basedb.util.extensions ;24 package net.sf.basedb.util.extensions.xml; 25 25 26 26 import java.io.IOException; … … 28 28 import java.lang.reflect.InvocationTargetException; 29 29 import java.lang.reflect.Method; 30 import java.util.ArrayList; 30 31 import java.util.LinkedList; 31 32 import java.util.List; … … 39 40 import net.sf.basedb.util.Values; 40 41 import net.sf.basedb.util.XMLUtil; 42 import net.sf.basedb.util.extensions.AboutBean; 43 import net.sf.basedb.util.extensions.Action; 44 import net.sf.basedb.util.extensions.ActionFactory; 45 import net.sf.basedb.util.extensions.Extension; 46 import net.sf.basedb.util.extensions.ExtensionBean; 47 import net.sf.basedb.util.extensions.ExtensionPoint; 48 import net.sf.basedb.util.extensions.ExtensionPointBean; 49 import net.sf.basedb.util.extensions.Registry; 50 import net.sf.basedb.util.extensions.RendererFactory; 41 51 42 52 /** … … 61 71 use reflection to find a setter method for each sub-tag inside 62 72 the <code><parameters></code> tag. Here is an example: 73 63 74 <pre class="code"> 64 75 // XML contents … … 73 84 </pre> 74 85 75 The setter methods must be public and accept a single Stringparameter.86 The setter methods must be public and accept a single <code>String</code> parameter. 76 87 Tags that doesn't have a corresponding setter method are simply ignored. 77 88 The XML file format allows any tags as parameters, but only the first level 78 89 will be parsed. 90 91 <p> 92 The parameter values may be subject to conversion by one or more 93 {@link ValueConverter}:s. Converters are added to the loader 94 by {@link #addValueConverter(ValueConverter)} and are usually 95 implemented to react on method annotations. For example, the web 96 client uses this for path and variable substitution. 79 97 80 98 @author nicklas … … 102 120 private List<Extension<Action>> extensions; 103 121 122 // List of registered converters 123 private List<ValueConverter> converters; 124 104 125 /** 105 126 Create a new XML loader instance. … … 109 130 extensionPoints = new LinkedList<ExtensionPoint<Action>>(); 110 131 extensions = new LinkedList<Extension<Action>>(); 132 } 133 134 135 public void addValueConverter(ValueConverter converter) 136 { 137 if (converters == null) converters = new ArrayList<ValueConverter>(); 138 converters.add(converter); 111 139 } 112 140 … … 390 418 { 391 419 Method setter = beanClass.getMethod(methodName, String.class); 420 421 // Convert input values 422 if (converters != null) 423 { 424 for (ValueConverter converter : converters) 425 { 426 value = converter.convert(value, setter); 427 } 428 } 392 429 setter.invoke(bean, value); 393 430 } … … 402 439 } 403 440 441 404 442 } -
branches/extensions/src/test/TestExtensions.java
r4169 r4170 28 28 import net.sf.basedb.util.extensions.Action; 29 29 import net.sf.basedb.util.extensions.ActionFactory; 30 import net.sf.basedb.util.extensions.XmlLoader;31 30 import net.sf.basedb.util.extensions.Context; 32 31 import net.sf.basedb.util.extensions.Extension; … … 36 35 import net.sf.basedb.util.extensions.Renderer; 37 36 import net.sf.basedb.util.extensions.RendererFactory; 37 import net.sf.basedb.util.extensions.xml.VariableConverter; 38 import net.sf.basedb.util.extensions.xml.VariableSetter; 39 import net.sf.basedb.util.extensions.xml.XmlLoader; 38 40 39 41 … … 97 99 98 100 XmlLoader loader = new XmlLoader(); 101 VariableConverter converter = new VariableConverter(); 102 converter.setVariable("HOME", "~"); 103 loader.addValueConverter(converter); 99 104 loader.loadXmlFile(in, xmlFile, null); 100 105 … … 127 132 128 133 XmlLoader loader = new XmlLoader(); 134 VariableConverter converter = new VariableConverter(); 135 converter.setVariable("HOME", "~"); 136 loader.addValueConverter(converter); 129 137 loader.loadXmlFile(in, xmlFile, null); 130 138 … … 177 185 { 178 186 private final String title; 179 public ActionButton(String title) 187 private final String icon; 188 189 public ActionButton(String title, String icon) 180 190 { 181 191 this.title = title; 192 this.icon = icon; 182 193 } 183 194 … … 185 196 { 186 197 return title; 198 } 199 200 public String getIcon() 201 { 202 return icon; 187 203 } 188 204 } … … 193 209 194 210 private String title; 211 private String icon; 195 212 private ActionButton button; 196 213 … … 199 216 200 217 @Override 201 public ActionButton[] getActions(Context context )218 public ActionButton[] getActions(Context context, Extension<? super ActionButton> extension) 202 219 { 203 220 if (button == null) 204 221 { 205 button = new ActionButton(title );222 button = new ActionButton(title, icon); 206 223 } 207 224 return new ActionButton[] { button }; … … 209 226 210 227 @Override 211 public boolean prepareContext(Context context )228 public boolean prepareContext(Context context, Extension<? super ActionButton> extension) 212 229 { 213 230 return true; … … 217 234 { 218 235 this.title = title; 236 } 237 238 @VariableSetter 239 public void setIcon(String icon) 240 { 241 this.icon = icon; 219 242 } 220 243 … … 236 259 237 260 @Override 238 public Renderer<ActionButton> getRenderer(Context context) 261 public void prepareContext(Context context, Extension<? extends ActionButton> extension) 262 { 263 } 264 265 @Override 266 public Renderer<ActionButton> getRenderer(Context context, Extension<? extends ActionButton> extension) 239 267 { 240 268 return this; … … 247 275 { 248 276 System.out.println("<div class=\"actionbutton\" style=\"color: " + 249 color + ";\">" + action.getTitle() + "</div>"); 277 color + ";\"><img src=\"" + action.getIcon() + "\">" + 278 action.getTitle() + "</div>"); 250 279 } 251 280 } -
branches/extensions/src/test/data/test.extensions.xml
r4163 r4170 48 48 <parameters> 49 49 <title>Launch MeV</title> 50 <icon>$HOME$/images/mev.png</icon> 50 51 </parameters> 51 52 </action-factory> … … 61 62 <parameters> 62 63 <title>Mage export</title> 64 <icon>/images/mev.png</icon> 63 65 </parameters> 64 66 </action-factory> -
branches/extensions/www/WEB-INF/extensions/test-extensions.xml
r4168 r4170 98 98 <parameters> 99 99 <title>Launch MeV</title> 100 <icon> ../../../images/tm4.png</icon>100 <icon>/images/tm4.png</icon> 101 101 <onClick>net_sf_launchMeV</onClick> 102 102 </parameters> … … 116 116 <parameters> 117 117 <title>Create MAGE</title> 118 <icon> ../../../images/copy.gif</icon>118 <icon>/images/copy.gif</icon> 119 119 <onClick>alert('Are you sure?')</onClick> 120 120 </parameters> -
branches/extensions/www/views/experiments/bioassaysets/analysis_tree.jsp
r4168 r4170 288 288 <% 289 289 jspContext.setOut(out); 290 jspContext.writeScripts( rootPath);290 jspContext.writeScripts(); 291 291 %> 292 292 <script language="JavaScript">
Note: See TracChangeset
for help on using the changeset viewer.