Enhancements to Tool client-server interactions: (a) use DictifiableMixin to dictify toolbox, tools, and tool inputs + outputs; (b) integrate code from visual analytics module with tool/parameter code base and remove VA module; (c) harmonize class names for tool panel on server and client side; (d) update client-side tool panel code and trackster code to work with server-side enhancements. Pack scripts.

This commit is contained in:
Jeremy Goecks
2013-08-21 13:01:53 -04:00
parent 89c8698169
commit 6e5607c32d
18 changed files with 218 additions and 209 deletions
+1 -1
View File
@@ -1508,7 +1508,7 @@ class DatasetInstance( object ):
return msg
class HistoryDatasetAssociation( DatasetInstance, UsesAnnotations ):
class HistoryDatasetAssociation( DatasetInstance, DictifiableMixin, UsesAnnotations ):
"""
Resource class that creates a relation between a dataset and a user history.
"""
+1 -1
View File
@@ -193,7 +193,7 @@ class DictifiableMixin:
try:
visible_keys = self.__getattribute__( 'dict_' + view + '_visible_keys' )
except AttributeError:
raise Exception( 'Unknown API view: %s' % view )
raise Exception( 'Unknown DictifiableMixin view: %s' % view )
for key in visible_keys:
try:
item = self.__getattribute__( key )
+64 -72
View File
@@ -59,6 +59,7 @@ from galaxy.util.odict import odict
from galaxy.util.template import fill_template
from galaxy.web import url_for
from galaxy.web.form_builder import SelectField
from galaxy.model.item_attrs import DictifiableMixin
from tool_shed.util import shed_util_common
from .loader import load_tool, template_macro_params
@@ -92,7 +93,7 @@ class StdioErrorLevel( object ):
class ToolNotFoundException( Exception ):
pass
class ToolBox( object ):
class ToolBox( object, DictifiableMixin ):
"""Container for a collection of tools"""
def __init__( self, config_filenames, tool_root_dir, app ):
@@ -701,7 +702,7 @@ class ToolBox( object ):
"""
return self.app.model.context
def to_dict( self, trans, in_panel=True, **kwds ):
def dictify( self, trans, in_panel=True, **kwds ):
"""
Dictify toolbox.
"""
@@ -722,11 +723,11 @@ class ToolBox( object ):
# Produce panel.
rval = []
for elt in panel_elts:
rval.append( elt.to_dict( trans, for_link=True ) )
rval.append( elt.dictify( trans, link_details=True ) )
else:
tools = []
for id, tool in self.tools_by_id.items():
tools.append( tool.to_dict( trans, for_link=True ) )
tools.append( tool.dictify( trans, link_details=True ) )
rval = tools
return rval
@@ -787,11 +788,14 @@ def _filter_for_panel( item, filters, context ):
class ToolSection( object ):
class ToolSection( object, DictifiableMixin ):
"""
A group of tools with similar type/purpose that will be displayed as a
group in the user interface.
"""
dict_collection_visible_keys = ( 'id', 'name', 'version' )
def __init__( self, elem=None ):
f = lambda elem, val: elem is not None and elem.get( val ) or ''
self.name = f( elem, 'name' )
@@ -807,27 +811,33 @@ class ToolSection( object ):
copy.elems = self.elems.copy()
return copy
def to_dict( self, trans, for_link=False ):
def dictify( self, trans, link_details=False ):
""" Return a dict that includes section's attributes. """
section_dict = super( ToolSection, self ).dictify()
section_elts = []
for key, val in self.elems.items():
section_elts.append( val.to_dict( trans, for_link=for_link ) )
return { 'type': 'section', 'id': self.id, 'name': self.name, 'version': self.version, 'elems': section_elts }
if isinstance( val, ToolSectionLabel ):
section_elts.append( val.dictify() )
else:
section_elts.append( val.dictify( trans, link_details=link_details ) )
section_dict[ 'elems' ] = section_elts
class ToolSectionLabel( object ):
return section_dict
class ToolSectionLabel( object, DictifiableMixin ):
"""
A label for a set of tools that can be displayed above groups of tools
and sections in the user interface
"""
dict_collection_visible_keys = ( 'id', 'text', 'version' )
def __init__( self, elem ):
self.text = elem.get( "text" )
self.id = elem.get( "id" )
self.version = elem.get( "version" ) or ''
def to_dict( self, trans, **kwargs ):
""" Return a dict that includes label's attributes. """
return { 'type': 'label', 'id': self.id, 'name': self.text, 'version': self.version }
class DefaultToolState( object ):
"""
Keeps track of the state of a users interaction with a tool between
@@ -874,7 +884,7 @@ class DefaultToolState( object ):
self.rerun_remap_job_id = None
self.inputs = params_from_strings( tool.inputs, values, app, ignore_errors=True )
class ToolOutput( object ):
class ToolOutput( object, DictifiableMixin ):
"""
Represents an output datasets produced by a tool. For backward
compatibility this behaves as if it were the tuple::
@@ -882,6 +892,8 @@ class ToolOutput( object ):
(format, metadata_source, parent)
"""
dict_collection_visible_keys = ( 'name', 'format', 'label', 'hidden' )
def __init__( self, name, format=None, format_source=None, metadata_source=None,
parent=None, label=None, filters = None, actions = None, hidden=False ):
self.name = name
@@ -912,14 +924,6 @@ class ToolOutput( object ):
def __iter__( self ):
return iter( ( self.format, self.metadata_source, self.parent ) )
def to_dict( self ):
return {
'name': self.name,
'format': self.format,
'label': self.label,
'hidden': self.hidden
}
class ToolRequirement( object ):
"""
Represents an external requirement that must be available for the tool to run (for example, a program, package, or library).
@@ -930,13 +934,14 @@ class ToolRequirement( object ):
self.type = type
self.version = version
class Tool( object ):
class Tool( object, DictifiableMixin ):
"""
Represents a computational tool that can be executed through Galaxy.
"""
tool_type = 'default'
default_tool_action = DefaultToolAction
dict_collection_visible_keys = ( 'id', 'name', 'version', 'description' )
def __init__( self, config_file, root, app, guid=None, repository_id=None ):
"""Load a tool from the config named by `config_file`"""
@@ -1225,7 +1230,6 @@ class Tool( object ):
# Trackster configuration.
trackster_conf = root.find( "trackster_conf" )
if trackster_conf is not None:
from galaxy.visualization.genome.visual_analytics import TracksterConfig
self.trackster_conf = TracksterConfig.parse( trackster_conf )
else:
self.trackster_conf = None
@@ -2944,66 +2948,29 @@ class Tool( object ):
self.sa_session.flush()
return primary_datasets
def to_dict( self, trans, for_link=False, for_display=False ):
def dictify( self, trans, link_details=False, io_details=False ):
""" Returns dict of tool. """
# Basic information
tool_dict = { 'id': self.id, 'name': self.name,
'version': self.version, 'description': self.description }
if for_link:
# Create tool link.
tool_dict = super( Tool, self ).dictify()
# Add link details.
if link_details:
# Add details for creating a hyperlink to the tool.
if not self.tool_type.startswith( 'data_source' ):
link = url_for( '/tool_runner', tool_id=self.id )
else:
link = url_for( self.action, **self.get_static_param_values( trans ) )
# Basic information
tool_dict.update( { 'type': 'tool', 'link': link,
tool_dict.update( { 'link': link,
'min_width': self.uihints.get( 'minwidth', -1 ),
'target': self.target } )
if for_display:
# Dictify inputs.
inputs = []
for name, input in self.inputs.items():
param_dict = { 'name' : name, 'label' : input.label }
if isinstance( input, DataToolParameter ):
param_dict.update( { 'type' : 'data', 'html' : urllib.quote( input.get_html( trans ) ) } )
elif isinstance( input, SelectToolParameter ):
# Get options, value.
options = input.get_options( trans, [] )
value = options[0][1]
for option in options:
if option[2]:
# Found selected option.
value = option[1]
# Pack input.
param_dict.update( { 'type' : 'select',
'html' : urllib.quote( input.get_html( trans ) ),
'options': options,
'value': value
} )
elif isinstance( input, Conditional ):
# TODO.
pass
elif isinstance( input, ( IntegerToolParameter, FloatToolParameter ) ):
param_dict.update( { 'type' : 'number', 'init_value' : input.value,
'html' : urllib.quote( input.get_html( trans ) ),
'min': input.min,
'max': input.max,
'value': input.value
} )
else:
param_dict.update( { 'type' : '??', 'init_value' : input.value, \
'html' : urllib.quote( input.get_html( trans ) ) } )
inputs.append( param_dict )
tool_dict[ 'inputs' ] = inputs
# Dictify outputs.
pass
# Add input and output details.
if io_details:
tool_dict[ 'inputs' ] = [ input.dictify( trans ) for input in self.inputs.values() ]
tool_dict[ 'outputs' ] = [ output.dictify() for output in self.outputs.values() ]
return tool_dict
@@ -3240,6 +3207,31 @@ for tool_class in [ Tool, DataDestinationTool, SetMetadataTool, DataSourceTool,
# ---- Utility classes to be factored out -----------------------------------
class TracksterConfig:
""" Trackster configuration encapsulation. """
def __init__( self, actions ):
self.actions = actions
@staticmethod
def parse( root ):
actions = []
for action_elt in root.findall( "action" ):
actions.append( SetParamAction.parse( action_elt ) )
return TracksterConfig( actions )
class SetParamAction:
""" Set parameter action. """
def __init__( self, name, output_name ):
self.name = name
self.output_name = output_name
@staticmethod
def parse( elt ):
""" Parse action from element. """
return SetParamAction( elt.get( "name" ), elt.get( "output_name" ) )
class BadValue( object ):
def __init__( self, value ):
self.value = value
+41 -4
View File
@@ -2,7 +2,7 @@
Basic tool parameters.
"""
import logging, string, sys, os, os.path
import logging, string, sys, os, os.path, urllib
from elementtree.ElementTree import XML, Element
from galaxy import config, datatypes, util
from galaxy.web import form_builder
@@ -12,16 +12,19 @@ from sanitize import ToolParameterSanitizer
import validation, dynamic_options
# For BaseURLToolParameter
from galaxy.web import url_for
from galaxy.model.item_attrs import DictifiableMixin
import galaxy.model
log = logging.getLogger(__name__)
class ToolParameter( object ):
class ToolParameter( object, DictifiableMixin ):
"""
Describes a parameter accepted by a tool. This is just a simple stub at the
moment but in the future should encapsulate more complex parameters (lists
of valid choices, validation logic, ...)
"""
dict_collection_visible_keys = ( 'name', 'type', 'label', 'help' )
def __init__( self, tool, param, context=None ):
self.tool = tool
self.refresh_on_change = False
@@ -167,6 +170,15 @@ class ToolParameter( object ):
for validator in self.validators:
validator.validate( value, history )
def dictify( self, trans, view='collection', value_mapper=None ):
""" Dictify tool parameter. This can be overridden by subclasses. """
tool_dict = super( ToolParameter, self ).dictify()
tool_dict[ 'html' ] = urllib.quote( self.get_html( trans ) )
if hasattr( self, 'value' ):
tool_dict[ 'value' ] = self.value
return tool_dict
@classmethod
def build( cls, tool, param ):
"""Factory method to create parameter of correct type"""
@@ -223,6 +235,9 @@ class IntegerToolParameter( TextToolParameter ):
...
ValueError: An integer is required
"""
dict_colletion_visible_keys = ToolParameter.dict_collection_visible_keys + ( 'min', 'max' )
def __init__( self, tool, elem ):
TextToolParameter.__init__( self, tool, elem )
if self.value:
@@ -276,7 +291,7 @@ class IntegerToolParameter( TextToolParameter ):
return int( self.value )
else:
return None
class FloatToolParameter( TextToolParameter ):
"""
Parameter that takes a real number value.
@@ -293,6 +308,9 @@ class FloatToolParameter( TextToolParameter ):
...
ValueError: A real number is required
"""
dict_collection_visible_keys = ToolParameter.dict_collection_visible_keys + ( 'min', 'max' )
def __init__( self, tool, elem ):
TextToolParameter.__init__( self, tool, elem )
self.min = elem.get( 'min' )
@@ -854,6 +872,24 @@ class SelectToolParameter( ToolParameter ):
else:
return []
def dictify( self, trans, view='collection', value_mapper=None ):
d = super( SelectToolParameter, self ).dictify( trans )
# Get options, value.
options = self.get_options( trans, [] )
value = options[0][1]
for option in options:
if option[2]:
# Found selected option.
value = option[1]
d.update( {
'options': options,
'value': value
} )
return d
class GenomeBuildParameter( SelectToolParameter ):
"""
Select list that sets the last used genome build for the current history
@@ -1680,7 +1716,7 @@ class DataToolParameter( ToolParameter ):
if call_attribute:
ref = ref()
return ref
class HiddenDataToolParameter( HiddenToolParameter, DataToolParameter ):
"""
Hidden parameter that behaves as a DataToolParameter. As with all hidden
@@ -1689,6 +1725,7 @@ class HiddenDataToolParameter( HiddenToolParameter, DataToolParameter ):
def __init__( self, tool, elem ):
DataToolParameter.__init__( self, tool, elem )
self.value = "None"
self.type = "hidden_data"
def get_initial_value( self, trans, context ):
return None
+15 -1
View File
@@ -15,30 +15,44 @@ from galaxy.util import relpath
from galaxy.util import sanitize_for_filename
from galaxy.util.bunch import Bunch
from galaxy.util.expressions import ExpressionContext
from galaxy.model.item_attrs import DictifiableMixin
class Group( object, DictifiableMixin ):
dict_collection_visible_keys = ( 'name', 'type' )
class Group( object ):
def __init__( self ):
self.name = None
self.type = 'group'
@property
def visible( self ):
return True
def value_to_basic( self, value, app ):
"""
Convert value to a (possibly nested) representation using only basic
types (dict, list, tuple, str, unicode, int, long, float, bool, None)
"""
return value
def value_from_basic( self, value, app, ignore_errors=False ):
"""
Convert a basic representation as produced by `value_to_basic` back
into the preferred value form.
"""
return value
def get_initial_value( self, trans, context ):
"""
Return the initial state/value for this group
"""
raise TypeError( "Not implemented" )
def dictify( self, trans, view='collection', value_mapper=None ):
# TODO: need to dictify conditions.
group_dict = super( Group, self ).dictify( view=view, value_mapper=value_mapper )
return group_dict
class Repeat( Group ):
type = "repeat"
@@ -1,82 +0,0 @@
import urllib
from galaxy.tools.parameters.basic import IntegerToolParameter, FloatToolParameter, SelectToolParameter
from galaxy.tools.parameters.dynamic_options import DynamicOptions
class TracksterConfig:
""" Trackster configuration encapsulation. """
def __init__( self, actions ):
self.actions = actions
@staticmethod
def parse( root ):
actions = []
for action_elt in root.findall( "action" ):
actions.append( SetParamAction.parse( action_elt ) )
return TracksterConfig( actions )
class SetParamAction:
""" Set parameter action. """
def __init__( self, name, output_name ):
self.name = name
self.output_name = output_name
@staticmethod
def parse( elt ):
""" Parse action from element. """
return SetParamAction( elt.get( "name" ), elt.get( "output_name" ) )
def get_dataset_job( hda ):
# Get dataset's job.
job = None
for job_output_assoc in hda.creating_job_associations:
job = job_output_assoc.job
break
return job
def get_tool_def( trans, hda ):
""" Returns definition of an interactive tool for an HDA. """
#FIXME: use tools.to_dict rather than custom code here.
job = get_dataset_job( hda )
# TODO: could use this assertion to provide more information.
# assert job is not None, 'Requested job has not been loaded.'
if not job:
return None
tool = trans.app.toolbox.get_tool( job.tool_id )
# TODO: could use this assertion to provide more information.
# assert tool is not None, 'Requested tool has not been loaded.'
if not tool:
return None
# Tool must have a Trackster configuration.
if not tool.trackster_conf:
return None
# Get list of tool parameters that can be interactively modified.
tool_params = []
tool_param_values = dict( [ ( p.name, p.value ) for p in job.parameters ] )
tool_param_values = tool.params_from_strings( tool_param_values, trans.app, ignore_errors=True )
for name, input in tool.inputs.items():
if type( input ) == IntegerToolParameter or type( input ) == FloatToolParameter:
param_dict = { 'name' : name, 'label' : input.label, \
'value' : tool_param_values.get( name, input.value ), \
'type' : 'number', 'init_value' : input.value,
'html' : urllib.quote( input.get_html() ) }
if input.min:
param_dict['min'] = input.min
if input.max:
param_dict['max'] = input.max
tool_params.append( param_dict )
elif type( input ) == SelectToolParameter and type( input.options ) != DynamicOptions:
tool_params.append( { 'name' : name, 'label' : input.label, 'type' : 'select', \
'value' : tool_param_values.get( name, '' ), \
'html' : urllib.quote( input.get_html() ) } )
# If tool has parameters that can be interactively modified, return tool.
if len( tool_params ) != 0:
return { 'id': tool.id, 'name' : tool.name, 'inputs' : tool_params }
return None
+2 -2
View File
@@ -73,7 +73,7 @@ class Genome( object ):
self.len_file = len_file
self.twobit_file = twobit_file
def to_dict( self, num=None, chrom=None, low=None ):
def dictify( self, num=None, chrom=None, low=None ):
"""
Returns representation of self as a dictionary.
"""
@@ -289,7 +289,7 @@ class Genomes( object ):
# Set up return value or log exception if genome not found for key.
rval = None
if genome:
rval = genome.to_dict( num=num, chrom=chrom, low=low )
rval = genome.dictify( num=num, chrom=chrom, low=low )
else:
log.exception( 'genome not found for key %s' % dbkey )
+44 -4
View File
@@ -32,12 +32,12 @@ from galaxy.workflow.modules import module_factory
from galaxy.model.orm import eagerload, eagerload_all
from galaxy.security.validate_user_input import validate_publicname
from galaxy.util.sanitize_html import sanitize_html
from galaxy.model.item_attrs import DictifiableMixin
from galaxy.datatypes.interval import ChromatinInteractions
from galaxy.datatypes.data import Text
from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation
from galaxy.visualization.genome.visual_analytics import get_tool_def
from galaxy.model import ExtendedMetadata, ExtendedMetadataIndex, LibraryDatasetDatasetAssociation,HistoryDatasetAssociation
from galaxy.datatypes.display_applications import util as da_util
from galaxy.datatypes.metadata import FileParameter
@@ -704,6 +704,15 @@ class UsesHistoryDatasetAssociationMixin:
return changed
def get_hda_job( self, hda ):
# Get dataset's job.
job = None
for job_output_assoc in hda.creating_job_associations:
job = job_output_assoc.job
break
return job
class UsesLibraryMixin:
@@ -1105,6 +1114,37 @@ class UsesVisualizationMixin( UsesHistoryDatasetAssociationMixin, UsesLibraryMix
encoded_id = trans.security.encode_id( vis.id )
return { "vis_id": encoded_id, "url": url_for( controller='visualization', action=vis.type, id=encoded_id ) }
def get_tool_def( self, trans, hda ):
""" Returns definition of an interactive tool for an HDA. """
job = self.get_hda_job( hda )
if not job:
return None
tool = trans.app.toolbox.get_tool( job.tool_id )
if not tool:
return None
# Tool must have a Trackster configuration.
if not tool.trackster_conf:
return None
# Get tool definition and add input values from job.
tool_dict = tool.dictify( trans, io_details=True )
inputs_dict = tool_dict[ 'inputs' ]
tool_param_values = dict( [ ( p.name, p.value ) for p in job.parameters ] )
tool_param_values = tool.params_from_strings( tool_param_values, trans.app, ignore_errors=True )
for t_input in inputs_dict:
# Add value to tool.
if 'name' in t_input:
name = t_input[ 'name' ]
if name in tool_param_values:
value = tool_param_values[ name ]
if isinstance( value, DictifiableMixin ):
value = value.dictify()
t_input[ 'value' ] = value
return tool_dict
def get_visualization_config( self, trans, visualization ):
""" Returns a visualization's configuration. Only works for trackster visualizations right now. """
config = None
@@ -1137,7 +1177,7 @@ class UsesVisualizationMixin( UsesHistoryDatasetAssociationMixin, UsesLibraryMix
"prefs": prefs,
"mode": track_dict.get( 'mode', 'Auto' ),
"filters": track_dict.get( 'filters', { 'filters' : track_data_provider.get_filters() } ),
"tool": get_tool_def( trans, dataset ),
"tool": self.get_tool_def( trans, dataset ),
"tool_state": track_dict.get( 'tool_state', {} )
}
@@ -1215,7 +1255,7 @@ class UsesVisualizationMixin( UsesHistoryDatasetAssociationMixin, UsesLibraryMix
"dataset": trans.security.encode_dict_ids( dataset.dictify() ),
"prefs": {},
"filters": { 'filters' : track_data_provider.get_filters() },
"tool": get_tool_def( trans, dataset ),
"tool": self.get_tool_def( trans, dataset ),
"tool_state": {}
}
+1 -1
View File
@@ -199,7 +199,7 @@ class DatasetsController( BaseAPIController, UsesVisualizationMixin, UsesHistory
data_dict = self.app.genomes.reference( trans, dbkey=dataset.dbkey, chrom=chrom, low=low, high=high )
if data_dict:
ref_seq = data_dict[ 'data' ]
# Get and return data from data_provider.
result = data_provider.get_data( chrom, int( low ), int( high ), int( start_val ), int( max_vals ),
ref_seq=ref_seq, **kwargs )
+3 -4
View File
@@ -1,6 +1,5 @@
from galaxy import web, util
from galaxy.web.base.controller import BaseAPIController, UsesHistoryDatasetAssociationMixin, UsesVisualizationMixin
from galaxy.visualization.genome.visual_analytics import get_dataset_job
from galaxy.visualization.genomes import GenomeRegion
from galaxy.util.json import to_json_string, from_json_string
from galaxy.visualization.data_providers.genome import *
@@ -33,7 +32,7 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin ):
# Create return value.
try:
return self.app.toolbox.to_dict( trans, in_panel=in_panel, trackster=trackster )
return self.app.toolbox.dictify( trans, in_panel=in_panel, trackster=trackster )
except Exception, exc:
log.error( 'could not convert toolbox to dictionary: %s', str( exc ), exc_info=True )
trans.response.status = 500
@@ -46,7 +45,7 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin ):
Returns tool information, including parameters and inputs.
"""
try:
return self.app.toolbox.tools_by_id[ id ].to_dict( trans, for_display=True )
return self.app.toolbox.tools_by_id[ id ].dictify( trans, for_display=True )
except Exception, exc:
log.error( 'could not convert tool (%s) to dictionary: %s', id, str( exc ), exc_info=True )
trans.response.status = 500
@@ -217,7 +216,7 @@ class ToolsController( BaseAPIController, UsesVisualizationMixin ):
# job's previous parameters and incoming parameters. Incoming parameters
# have priority.
#
original_job = get_dataset_job( original_dataset )
original_job = self.get_hda_job( original_dataset )
tool = trans.app.toolbox.get_tool( original_job.tool_id )
if not tool:
return trans.app.model.Dataset.conversion_messages.NO_TOOL
@@ -14,7 +14,6 @@ from galaxy.datatypes.interval import Bed
from galaxy.util.json import from_json_string
from galaxy.util.sanitize_html import sanitize_html
from galaxy.visualization.genomes import decode_dbkey
from galaxy.visualization.genome.visual_analytics import get_dataset_job
from galaxy.visualization.data_providers.phyloviz import PhylovizDataProvider
from galaxy.visualization.genomes import GenomeRegion
@@ -865,7 +864,7 @@ class VisualizationController( BaseUIController, SharableMixin, UsesAnnotations,
else:
# Loading new visualization.
dataset = self.get_hda_or_ldda( trans, hda_ldda, dataset_id )
job = get_dataset_job( dataset )
job = self.get_hda_job( dataset )
viz_config = {
'dataset_id': dataset_id,
'tool_id': job.tool_id,
@@ -874,7 +873,7 @@ class VisualizationController( BaseUIController, SharableMixin, UsesAnnotations,
# Add tool, dataset attributes to config based on id.
tool = trans.app.toolbox.get_tool( viz_config[ 'tool_id' ] )
viz_config[ 'tool' ] = tool.to_dict( trans, for_display=True )
viz_config[ 'tool' ] = tool.dictify( trans, for_display=True )
viz_config[ 'dataset' ] = dataset.dictify()
return trans.fill_template_mako( "visualization/sweepster.mako", config=viz_config )
+24 -22
View File
@@ -268,12 +268,12 @@ var ToolCollection = Backbone.Collection.extend({
/**
* Label or section header in tool panel.
*/
var ToolPanelLabel = Backbone.Model.extend(VisibilityMixin);
var ToolSectionLabel = Backbone.Model.extend(VisibilityMixin);
/**
* Section of tool panel with elements (labels and tools).
*/
var ToolPanelSection = Backbone.Model.extend({
var ToolSection = Backbone.Model.extend({
defaults: {
elems: [],
open: false
@@ -292,7 +292,7 @@ var ToolPanelSection = Backbone.Model.extend({
var all_hidden = true,
cur_label;
_.each(this.attributes.elems, function(elt) {
if (elt instanceof ToolPanelLabel) {
if (elt instanceof ToolSectionLabel) {
cur_label = elt;
cur_label.hide();
}
@@ -315,7 +315,7 @@ var ToolPanelSection = Backbone.Model.extend({
}
}
});
_.extend(ToolPanelSection.prototype, VisibilityMixin);
_.extend(ToolSection.prototype, VisibilityMixin);
/**
* Tool search that updates results when query is changed. Result value of null
@@ -399,18 +399,20 @@ var ToolPanel = Backbone.Model.extend({
var self = this,
// Helper to recursively parse tool panel.
parse_elt = function(elt_dict) {
var type = elt_dict.type;
if (type === 'tool') {
var type = elt_dict.model_class;
// There are many types of tools; for now, anything that ends in 'Tool'
// is treated as a generic tool.
if ( type.indexOf('Tool') === type.length - 4 ) {
return self.attributes.tools.get(elt_dict.id);
}
else if (type === 'section') {
else if (type === 'ToolSection') {
// Parse elements.
var elems = _.map(elt_dict.elems, parse_elt);
elt_dict.elems = elems;
return new ToolPanelSection(elt_dict);
return new ToolSection(elt_dict);
}
else if (type === 'label') {
return new ToolPanelLabel(elt_dict);
else if (type === 'ToolSectionLabel') {
return new ToolSectionLabel(elt_dict);
}
};
@@ -419,7 +421,7 @@ var ToolPanel = Backbone.Model.extend({
clear_search_results: function() {
this.get('layout').each(function(panel_elt) {
if (panel_elt instanceof ToolPanelSection) {
if (panel_elt instanceof ToolSection) {
panel_elt.clear_search_results();
}
else {
@@ -438,7 +440,7 @@ var ToolPanel = Backbone.Model.extend({
var cur_label = null;
this.get('layout').each(function(panel_elt) {
if (panel_elt instanceof ToolPanelLabel) {
if (panel_elt instanceof ToolSectionLabel) {
cur_label = panel_elt;
cur_label.hide();
}
@@ -495,12 +497,12 @@ var ToolLinkView = BaseView.extend({
/**
* Panel label/section header.
*/
var ToolPanelLabelView = BaseView.extend({
var ToolSectionLabelView = BaseView.extend({
tagName: 'div',
className: 'toolPanelLabel',
className: 'ToolSectionLabel',
render: function() {
this.$el.append( $("<span/>").text(this.model.attributes.name) );
this.$el.append( $("<span/>").text(this.model.attributes.text) );
return this;
}
});
@@ -508,7 +510,7 @@ var ToolPanelLabelView = BaseView.extend({
/**
* Panel section.
*/
var ToolPanelSectionView = BaseView.extend({
var ToolSectionView = BaseView.extend({
tagName: 'div',
className: 'toolSectionWrapper',
template: Handlebars.templates.panel_section,
@@ -528,8 +530,8 @@ var ToolPanelSectionView = BaseView.extend({
tool_view.render();
section_body.append(tool_view.$el);
}
else if (elt instanceof ToolPanelLabel) {
var label_view = new ToolPanelLabelView({model: elt});
else if (elt instanceof ToolSectionLabel) {
var label_view = new ToolSectionLabelView({model: elt});
label_view.render();
section_body.append(label_view.$el);
}
@@ -630,8 +632,8 @@ var ToolPanelView = Backbone.View.extend({
// Render panel.
this.model.get('layout').each(function(panel_elt) {
if (panel_elt instanceof ToolPanelSection) {
var section_title_view = new ToolPanelSectionView({model: panel_elt});
if (panel_elt instanceof ToolSection) {
var section_title_view = new ToolSectionView({model: panel_elt});
section_title_view.render();
self.$el.append(section_title_view.$el);
}
@@ -640,8 +642,8 @@ var ToolPanelView = Backbone.View.extend({
tool_view.render();
self.$el.append(tool_view.$el);
}
else if (panel_elt instanceof ToolPanelLabel) {
var label_view = new ToolPanelLabelView({model: panel_elt});
else if (panel_elt instanceof ToolSectionLabel) {
var label_view = new ToolSectionLabelView({model: panel_elt});
label_view.render();
self.$el.append(label_view.$el);
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+14 -6
View File
@@ -1634,7 +1634,17 @@ var TracksterTool = Backbone.RelationalModel.extend({
key: 'tool',
relatedModel: tools_mod.Tool
}
]
],
initialize: function(options) {
// HACK: remove data and group tool inputs because Trackster
// does not work with them right now.
var tool = this.get('tool'),
incompatible_inputs = tool.get('inputs').filter( function(input) {
return ( [ 'data', 'hidden_data', 'group'].indexOf( input.get('type') ) !== -1);
});
tool.get('inputs').remove(incompatible_inputs);
}
});
@@ -1692,6 +1702,7 @@ var TracksterToolView = Backbone.View.extend({
// Add name, inputs.
var name_div = $("<div class='tool-name'>").appendTo(parent_div).text(tool.get('name'));
tool.get('inputs').each(function(param) {
// Render parameter.
var param_view = new ToolParameterView({ model: param });
param_view.render();
parent_div.append(param_view.$el);
@@ -2479,11 +2490,8 @@ extend(Track.prototype, Drawable.prototype, {
Drawable.prototype.action_icons_def[2]
],
can_draw: function() {
if ( this.dataset.id && Drawable.prototype.can_draw.call(this) ) {
return true;
}
return false;
can_draw: function() {
return this.dataset && Drawable.prototype.can_draw.call(this);
},
build_container_div: function () {
+2 -2
View File
@@ -25,12 +25,12 @@
hidden: false
}),
tools = new tools_mod.ToolCollection(
${ h.to_json_string( trans.app.toolbox.to_dict( trans, in_panel=False ) ) }
${ h.to_json_string( trans.app.toolbox.dictify( trans, in_panel=False ) ) }
),
tool_panel = new tools_mod.ToolPanel({
tool_search: tool_search,
tools: tools,
layout: ${h.to_json_string( trans.app.toolbox.to_dict( trans ) )}
layout: ${h.to_json_string( trans.app.toolbox.dictify( trans ) )}
}),
tool_panel_view = new tools_mod.ToolPanelView({ model: tool_panel });