Commit c2d083d8 authored by Sebastien Robin's avatar Sebastien Robin

first submission


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@2861 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent a7b1fa9a
##############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jonathan Loriette <john@nexedi.com>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import string, types, sys
from Form import BasicForm
from Products.Formulator.Field import ZMIField
from Products.Formulator.DummyField import fields
from Products.Formulator.MethodField import BoundMethod
from DateTime import DateTime
from Products.Formulator import Widget, Validator
from Products.Formulator.Errors import FormValidationError, ValidationError
from Selection import Selection, DomainSelection
from SelectionTool import makeTreeList
import OFS
from AccessControl import ClassSecurityInfo
from zLOG import LOG
from copy import copy
from Acquisition import aq_base, aq_inner, aq_parent, aq_self
from Products.Formulator.Form import BasicForm
from Products.ERP5Type.Utils import getPath
from Products.ERP5Type.Document import newTempBase
from Products.CMFCore.utils import getToolByName
class PlanningBoxValidator(Validator.StringBaseValidator):
def validate(self, field, key, REQUEST):
try:
for lang in list_value.keys():
list_value[lang] = int(list_value[lang])
except ValueError:
self.raise_error('not an integer', field)
return list_value
PlanningBoxValidatorInstance=PlanningBoxValidator()
def createLineObject(meta_types,selection,selection_name,field,REQUEST,list_method,
here,report_root_list,y_axis_width,width_line,space_line,
height_global_div,height_header,height_axis_x,form,current_top):
report_sections = []
section_index = 0
if len(report_sections) > section_index:
current_section = report_sections[section_index]
elif len(report_sections):
current_section = report_sections[0]
else:
current_section = None
filtered_meta_types = map(lambda x: x[0], meta_types)
params = selection.getParams()
sort = field.get_value('sort')
kw=params
report_depth = REQUEST.get('report_depth', None)
is_report_opened = REQUEST.get('is_report_opened', selection.isReportOpened())
portal_categories = getattr(form, 'portal_categories', None)
if 'select_expression' in kw:
del kw['select_expression']
if hasattr(list_method, 'method_name'):
list_method = here.objectValues
kw = copy(params)
kw['spec'] = filtered_meta_types
elif list_method in (None, ''): # Use current selection
# Use previously used list method
list_method = None
select_expression = ''
default_selection_report_path = report_root_list[0][0].split('/')[0]
if default_selection_report_path in portal_categories.objectIds() or \
(portal_domains is not None and default_selection_report_path in portal_domains.objectIds()):
pass
else:
default_selection_report_path = report_root_list[0][0]
selection_report_path = selection.getReportPath(default = (default_selection_report_path,))
if report_depth is not None:
selection_report_current = ()
else:
selection_report_current = selection.getReportList()
report_tree_list = makeTreeList(here, form, None,selection_report_path,None,0,
selection_report_current, form.id, selection_name,
report_depth,is_report_opened, sort_on=selection.sort_on)
# Update report list if report_depth was specified
if report_depth is not None:
report_list = map(lambda s:s[0].getRelativeUrl(), report_tree_list)
selection.edit(report_list=report_list)
report_sections = []
list_object = []
nbr_line=0
object_list=[]
indic_line=0
index_line = 0
for s in report_tree_list:
selection.edit(report = s.getSelectDomainDict())
if s.getIsPureSummary():
original_select_expression = kw.get('select_expression')
kw['select_expression'] = select_expression
selection.edit( params = kw )
if original_select_expression is None:
del kw['select_expression']
else:
kw['select_expression'] = original_select_expression
if s.getIsPureSummary():
stat_result = {}
index = 1
report_sections += [s]
nbr_line+=1
else:
# Prepare query
selection.edit( params = kw )
if list_method not in (None, ''):
object_list = selection(method = list_method, context=here, REQUEST=REQUEST,
s=s, object_list= object_list)
else:
object_list = here.portal_selections.getSelectionValueList(selection_name,
context=here, REQUEST=REQUEST)
selection.edit(report=None)
index = 0
# we start to build our line object structure right here.
for l in report_sections:
stat_result = {}
stat_context = l.getObject().asContext(**stat_result)
stat_context.domain_url = l.getObject().getRelativeUrl()
stat_context.absolute_url = lambda x: l.getObject().absolute_url()
url=getattr(stat_context,'domain_url','')
if l.getDepth() == 0:
paternity = 0
if len(l.getObject().objectValues())!=0:
paternity = 1
height=(height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)
line = Line(title=l.getObject().getTitle(),
name='fra' + str(indic_line),
begin=y_axis_width,
width=width_line,
height=height,
top=current_top,color='#ffffff',
paternity=paternity,url=url)
list_object.append(line)
if paternity == 0:
current_top=current_top+((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)) + (space_line)
else:
if (index+1)<=(len(report_sections)-1):
if report_sections[index+1].getDepth()==0:
#current_top=current_top+((height_global_div-height_header-height_axis_x)/float(nbr_line)) + (space_line)
current_top=current_top+((height_global_div-height_header-height_axis_x-(((nbr_line-1))*space_line))/float(nbr_line))+ (space_line)
else:
current_top=current_top+((height_global_div-height_header-height_axis_x-(((nbr_line-1))*space_line))/float(nbr_line))
else:
current_index = 0
while l.getDepth() == report_sections[index-current_index].getDepth():
current_index += 1
if report_sections[index-current_index].getDepth() == 0:
current_top=list_object[len(list_object)-1].createLineChild(report_sections,field,current_top,y_axis_width,width_line,space_line,height_global_div,height_header,height_axis_x,nbr_line,index,url)
else : # in this case wee add a soon to a soon
depth=0
current_soon=list_object[len(list_object)-1]
while depth != (l.getDepth()-1):
current_soon=list_object[len(list_object)-1].soon[len(list_object[len(list_object)-1].soon)-1]
depth+=1
current_top=current_soon.createLineChild(report_sections,field,current_top,y_axis_width,width_line,space_line,height_global_div,height_header,height_axis_x,nbr_line,index,url)
index += 1
indic_line+=1
return (list_object,nbr_line,report_sections)
def createGraphicCall(current_line,graphic_call):
""" create html code of children used by graphic library to know which block can be moved"""
for i in current_line.soon:
for j in i.content:
if j.types=='activity':
graphic_call+='\"'+j.name+'\",'
elif j.types=='info':
graphic_call+='\"'+j.name+'\"+NO_DRAG,'
if i.soon!=[]: # case of a soon which has soons...
graphic_call+=createGraphicCall(i,graphic_call)
return graphic_call
#class planningboxwidget *********************************
class PlanningBoxWidget(Widget.Widget):
property_names = Widget.Widget.property_names +\
['height_header', 'height_global_div','height_axis_x', 'width_line','space_line','list_method','report_tree','report_root_list','selection_name','portal_types','meta_types','sort','title_line','y_unity','y_axis_width','y_range','x_range','x_axis_script_id','x_start_bloc','x_stop_bloc','y_axis_method','info_block_method','security_index']
default = fields.TextAreaField('default',
title='Default',
description=(
"Default value of the text in the widget."),
default="",
width=20, height=3,
required=0)
height_header = fields.IntegerField('height_header',
title='height of the header (px):',
description=(
"value of the height of the header, required"),
default=50,
required=1)
height_global_div = fields.IntegerField('height_global_div',
title='height of the graphic (px):',
description=(
"value of the height of the graphic, required"),
default=700,
required=1)
height_axis_x = fields.IntegerField('height_axis_x',
title='height of X-axis (px):',
description=(
"value of the height of X-axis"),
default=50,
required=1)
width_line = fields.IntegerField('width_line',
title='width of the graphic (px):',
description=(
"value of width_line, required"),
default=1000,
required=1)
space_line = fields.IntegerField('space_line',
title='space between each line of the graphic (px):',
description=(
"space between each line of the graphic,not required"),
default=10,
required=0)
report_tree = fields.CheckBoxField('report_tree',
title='Report Tree',
description=('Report Tree'),
default='',
required=0)
report_root_list = fields.ListTextAreaField('report_root_list',
title="Report Root",
description=(
"A list of domains which define the possible root."),
default=[],
required=0)
selection_name = fields.StringField('selection_name',
title='Selection Name',
description=('The name of the selection to store'
'params of selection'),
default='',
required=0)
portal_types = fields.ListTextAreaField('portal_types',
title="Portal Types",
description=(
"Portal Types of objects to list. Required."),
default=[],
required=0)
meta_types = fields.ListTextAreaField('meta_types',
title="Meta Types",
description=(
"Meta Types of objects to list. Required."),
default=[],
required=0)
sort = fields.ListTextAreaField('sort',
title='Default Sort',
description=('The default sort keys and order'),
default=[],
required=0)
list_method = fields.MethodField('list_method',
title='List Method',
description=('The method to use to list'
'objects'),
default='',
required=0)
title_line = fields.StringField('title_line',
title='specific method which fetches the title of each line: ',
description=('specific method for inserting title in line'),
default='',
required=0)
y_unity = fields.StringField('y_unity',
title='Unity in Y-axis:',
description=('The unity in Y-axis,not required'),
default='',
required=0)
y_axis_width = fields.IntegerField('y_axis_width',
title='width of Y-axis (px):',
description=(
"width of Y-axis, required"),
default=200,
required=1)
y_range = fields.IntegerField('y_range',
title='number of range of Y-axis :',
description=(
"Number of Range of Y-axis, not required"),
default=5,
required=0)
x_range = fields.StringField('x_range',
title='range of X-Axis:',
description=('Nature of the subdivisions of X-Axes, not Required'),
default='Day',
required=0)
x_axis_script_id = fields.StringField('x_axis_script_id',
title='script for building the X-Axis:',
description=('script for building the X-Axis'),
default='',
required=0)
x_start_bloc = fields.StringField('x_start_bloc',
title='specific method which fetches the data for the beginning of a block:',
description=('Method for building X-Axis such as getstartDate'
'objects'),
default='getStartDate',
required=0)
x_stop_bloc = fields.StringField('x_stop_bloc',
title='specific method which fetches the data for the end of each block',
description=('Method for building X-Axis such getStopDate'
'objects'),
default='',
required=0)
y_axis_method = fields.StringField('y_axis_method',
title='specific method of data type for creating Y-Axis',
description=('Method for building Y-Axis'
'objects'),
default='',
required=0)
info_block_method = fields.StringField('info_block_method',
title='specific method for inserting infos in Block',
description=('Method for inserting info'
'objects'),
default='',
required=0)
security_index = fields.IntegerField('security_index',
title='variable depending of the type of web browser :',
description=("This variable is used because the rounds of each web browser seem to work differently"),
default=2,
required=0)
def render_css(self, field, key, value, REQUEST):
# DATA DEFINITION #############################################
height_header = field.get_value('height_header')
height_global_div = field.get_value('height_global_div')
height_axis_x=field.get_value('height_axis_x')
width_line = field.get_value('width_line')
space_line = field.get_value('space_line')
selection_name = field.get_value('selection_name')
security_index = field.get_value('security_index')
y_unity = field.get_value('y_unity')
y_axis_width = field.get_value('y_axis_width')
y_range = field.get_value('y_range')
portal_types= field.get_value('portal_types')
meta_types = field.get_value('meta_types')
x_range=field.get_value('x_range')
here = REQUEST['here']
list_method = field.get_value('list_method')
report_tree = field.get_value('report_tree')
report_root_list = field.get_value('report_root_list')
y_axis_method=field.get_value('y_axis_method')
script=getattr(here,field.get_value('x_axis_script_id'),None)
info_block_method = getattr(here,field.get_value('info_block_method'),None)
object_start_method_id = field.get_value('x_start_bloc')
object_stop_method_id= field.get_value('x_stop_bloc')
form = field.aq_parent
x_occurence=[] # contains datas of start and stop of each block like this [ [ [x1,x2],[x1,x2] ],[ [x1,x2],[x1,x2] ],.....] it is not directly coordinate but datas.
x_axe=[] # will contain what wee need to display in X-axis. contains: (data used for construction, display of x-axis)
yrange=[] # we store the value in Y-axis of each block
nbr=1
y_max=1
current_top=height_header
total=[]
list_object=[] #in this list we store all the objects of type Line
giant_string='' #will contain all the html code.
report_sections=[]
# END DATA DEFINITION ###########################################
# we fetch fold/unfold datas ######################
#here.portal_selections.setSelectionFor(selection_name, None)#put selection to null
selection = here.portal_selections.getSelectionFor(selection_name, REQUEST=REQUEST)
default_params = {}
sort = ()
if selection is None:
selection = Selection(params=default_params, default_sort_on = sort)
domain_list = list(selection.getDomainList())
here.portal_selections.setSelectionFor(selection_name, selection, REQUEST=REQUEST)
########################
#we build line ***************************
(list_object,nbr_line,report_sections)=createLineObject(meta_types,selection,selection_name,field,REQUEST,list_method,here,report_root_list,y_axis_width,width_line,space_line,height_global_div,height_header,height_axis_x,form,current_top)
# end build line ####################################################
#we build x_occurence (used for the range in x-Axis ##################################
for o in report_sections:
method_start = getattr(o.getObject(),object_start_method_id,None)
method_stop= getattr(o.getObject(),object_stop_method_id,None)
block_begin = method_start()
if method_stop!=None:
block_stop= method_stop()
else:
block_stop=None
x_occurence.append([block_begin,block_stop])
x_axe=script(x_occurence,x_range) #we call this script for the range in X-Axis
##################################################
# we add mobile block to the line object ###################################
indic_line=0
#for o report_sections:
for o in list_object:
if list_object != []:
list_object[indic_line].insertActivityBlock(report_sections[indic_line].getObject(),object_start_method_id,object_stop_method_id,x_axe,field)
indic_line+=1
# #############################################################
# at this point list_object contains our tree of datas. Then wee add others object for the graphic.
#one constructs the vertical dotted line **********************
marge_left=y_axis_width+width_line/float(len(x_axe[1]))
for i in list_object:
i.appendVerticalDottedLine(x_axe,width_line,marge_left)
#*************************************************************
#one constructs the maximum horizontal dotted line 10px under the top of the line***************
maximum_y=y_max
marge_top=10
if y_range!=0:
for i in list_object:
i.appendHorizontalDottedLine(marge_top,maximum_y,height_global_div,height_header,height_axis_x,nbr_line,y_range,y_max,current_section)
#end construct of horizontal dotted line ********************************************************
# we construct y-axis ******************************
way=[]
y=[]
level=0
current_top=height_header
idx=0
for i in list_object:
current_top=i.buildYtype(way,y,level,y_axis_width,height_global_div,height_header,height_axis_x,nbr_line,current_top,space_line,y_max,y_range,y_unity,selection_name,form)
#current_top=y[len(y)-1].top+((height_global_div-height_header-height_axis_x)/float(nbr_line))+space_line
current_top=y[len(y)-1].top+((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line))+space_line
idx+=1
list_object=y+list_object #we need to add the y-axis block at the beginning of our structure otherwise the display is not correct
#************************end construct y-axis
#build X axis ########################################
list_object.append(Line('','axis_x',y_axis_width,width_line,height_axis_x,current_top-space_line))
list_object[len(list_object)-1].createXAxis(x_axe,width_line,y_axis_width)
#***************************
SESSION = REQUEST.SESSION
SESSION.set('total',list_object)
SESSION.set('width_line',width_line)
SESSION.set('height_global', height_global_div)
SESSION.set('y_axis_width', y_axis_width)
SESSION.set('report_tree',report_tree)
SESSION.set('report_root_list',report_root_list)
SESSION.set('selection_name',selection_name)
for i in list_object:
giant_string+=i.render_css(y_axis_width,security_index)
return giant_string
def render(self,field, key, value, REQUEST):
here = REQUEST['here']
portal_url= here.portal_url()
SESSION = REQUEST.SESSION
total = SESSION.get('total')
width_line=SESSION.get('width_line')
height_global_div=SESSION.get('height_global')
y_axis_width=SESSION.get('y_axis_width')
report_tree=SESSION.get('report_tree')
report_root_list=SESSION.get('report_root_list')
selection_name=SESSION.get('selection_name')
giant_string='<input type=\"hidden\" name=\"list_selection_name\" value='+selection_name+' />\n'
giant_string+='<div id=\"global_block\" style=\"position:absolute;width:'+str(width_line+y_axis_width)+'px;height:'+str(height_global_div)+'px;background:#d5e6de;margin-left:-99px;border-style:solid;border-color:#000000;border-width:1px;margin-top:-21px\">\n'
#header of the graphic******************************************
giant_string+='<div id=\"header\" style=\"position:absolute;width:'+str(width_line+y_axis_width)+'px;height:'+str(height_global_div)+'px;background:#d5e6de;margin-left:20px;border-style:solid;border-color:#000000;border-width:1px;margin-top:1px\">'
##########################report tree
# Create the header of the table with the name of the columns
# Create also Report Tree Column if needed
if report_tree:
selection = here.portal_selections.getSelectionFor(selection_name, REQUEST=REQUEST)
selection_report_path = selection.getReportPath()
report_tree_options = ''
for c in report_root_list:
if c[0] == selection_report_path:
report_tree_options += """<option selected value="%s">%s</option>\n""" % (c[0], c[1])
else:
report_tree_options += """<option value="%s">%s</option>\n""" % (c[0], c[1])
report_popup = """<select name="report_root_url"
onChange="submitAction(this.form,'%s/portal_selections/setReportRoot')">
%s</select></div>""" % (here.getUrl(),report_tree_options)
giant_string += report_popup
else:
report_popup = ''
######################################
for i in range(0,len(total)):
giant_string+=total[i].render(portal_url,y_axis_width)
###################"
giant_string+='<div id=\"lefttop\" style=\"position:absolute;width:5px;height:5px;background:#a45d10\"></div>\n'
giant_string+='<div id=\"righttop\" style=\"position:absolute;width:5px;height:5px;background:#a45d10"></div>\n'
giant_string+='<div id=\"rightbottom\" style=\"position:absolute;width:5px;height:5px;background:#a45d10\"></div>\n'
giant_string+='<div id=\"leftbottom\" style=\"position:absolute;width:5px;height:5px;background:#a45d10\"></div>\n'
giant_string+='<script type=\"text/javascript\">\n SET_DHTML('
for i in range(0,len(total)):
graphic_call=''
for j in total[i].content:
if j.types=='activity':
giant_string+='\"'+j.name+'\",'
elif j.types=='info':
giant_string+='\"'+j.name+'\"+NO_DRAG,'
current_object=total[i]
if current_object.soon!=[]:
giant_string+=createGraphicCall(current_object,graphic_call)
giant_string+='\"lefttop\"+CURSOR_NW_RESIZE, \"righttop\"+CURSOR_NE_RESIZE, \"rightbottom\"+CURSOR_SE_RESIZE, \"leftbottom\"+CURSOR_SW_RESIZE);\n'
giant_string+='</script>\n </div> '
return giant_string
#***************************************************
# class line **************************************
class Line:
def __init__(self,title='',name='',begin=0,width=0,height=0,top=0,color='',soon=None,y_type='none',paternity=0,url=''):
if soon is None:
soon = []
self.title=title
self.name=name
self.begin=begin
self.width=width
self.height=height
self.top=top
self.content=[]
self.color=color
self.soon=soon
self.y_type=y_type
self.paternity=paternity
self.url=url
def render(self,portal_url,y_axis_width):
""" creates "pure" html code of the line, its Block, its soon """
html_render='<div id=\"'+self.name+'\"></div>\n'
for j in self.content:
if j.types=='activity':
if ((j.width*self.width)+(self.begin+j.begin*self.width)>self.width+y_axis_width): #checks if the block is too large for the end of the line if it is the case, one cuts the block
html_render+='<div id=\"'+j.name+'\" ondblclick=\"showGrips()\" onclick=\"dd.elements.'+j.name+'.resizeTo('+str(round(j.width*self.width))+','+ str(j.height*(self.height-10))+') \">'
elif ((self.begin+j.begin*self.width) < self.begin): #checks if the block starts before the beginning of the line
html_render+='<div id=\"'+j.name+'\" ondblclick=\"showGrips()\" onclick=\"if (dd.elements.'+j.name+'.moved==0){dd.elements.'+j.name+'.moveBy('+str(round(j.begin*self.width))+',0);dd.elements.'+j.name+'.resizeTo('+str(round(j.width*self.width))+','+ str(j.height*(self.height-10))+');dd.elements.'+j.name+'.moved=1} \">' # "done" is used because otherwise everytime we move the block it will execute moveby()
else:
html_render+='<div id=\"'+j.name+'\" ondblclick=\"showGrips()\">'
html_render+=j.render(self.width,self.height,portal_url,self.begin,y_axis_width) # we add info Block inside the div
html_render+='</div>\n'
elif j.types!='info':
html_render+='<div id=\"'+j.name+'\">'+str(j.text)+'</div>\n'
if self.soon!=[]:
for i in self.soon:
html_render+=i.render(portal_url,y_axis_width)
return html_render
def render_css(self,y_axis_width,security_index):
css_render='#'+self.name+'{position:absolute;\nborder-style:solid;\nborder-color:#53676e;\nborder-width:1px;\n'
if self.color!='':
css_render+='background:'+str(self.color)+';\n'
css_render+='height:'+str(self.height)+'px;\n'
css_render+='margin-left:'+str(self.begin)+'px;\n'
css_render+='margin-top:'+str(self.top)+'px;\n'
if self.y_type=='father1':
css_render+='border-bottom-width:0px;'
elif self.y_type=='soon1':
css_render+='border-top-width:0px;\nborder-bottom-width:0px;\n'
elif self.y_type=='soon2':
css_render+='border-top-width:0px;'
css_render+='width:'+str(self.width)+'px;\n}'
for j in self.content: #we generate block's css
if j.types=='activity':
css_render+='#'+j.name+'{position:absolute;\nbackground:#bdd2e7;\nborder-style:solid;\nborder-color:#53676e;\nborder-width:1px;\n'
css_render+='height:'+str((j.height*(self.height-10))-security_index)+'px;\n' #-10 because wee don't want a block sticked to border-top of the line
# text=str('%.2f' %maximum_y)+y_unity
if ((self.begin+j.begin*self.width) < self.begin): #checks if the block starts before the beginning of the line
css_render+='margin-left:'+str(self.begin)+'px;\n'
css_render+='width:'+str((j.width*self.width+j.begin*self.width))+'px;\n'
elif ((j.width*self.width)+(self.begin+j.begin*self.width)>self.width+y_axis_width): #checks if the block is too large for the end of the line. if it is the case, one cuts the block
css_render+='width:'+str(round(j.width*self.width)-((self.begin+j.begin*self.width+j.width*self.width)-(self.width+y_axis_width)))+'px;\n'
css_render+='margin-left:'+str(round(self.begin+j.begin*self.width))+'px;\n'
else:
css_render+='width:'+str(round(j.width*self.width))+'px;\n'
css_render+='margin-left:'+str(round(self.begin+j.begin*self.width))+'px;\n'
css_render+='margin-top:'+str(self.top+10+j.marge_top*(self.height-10))+'px;}\n'
css_render+=j.render_css(self.width,self.height-10,self,y_axis_width) # we add info Block inside the div
elif j.types=='text_x' :
css_render+='#'+j.name+'{position:absolute;\nborder-style:solid;\nborder-color:#53676e;\nborder-width:1px;\n'
css_render+='margin-left:'+str(j.begin)+'px;\n'
css_render+='margin-top:'+str(round(1+self.top+self.height/2))+'px;}\n'
elif j.types=='text_y':
css_render+='#'+j.name+'{position:absolute;\nborder-style:solid;\nborder-color:#53676e;\nborder-width:1px;\n'
css_render+='margin-left:'+str(self.width/4)+'px;\n'
css_render+='margin-top:'+str(round(1+self.top+self.height/2))+'px;\n'
css_render+='border-width:0px;}\n'
elif j.types=='vertical_dotted':
css_render+='#'+j.name+'{position:absolute;\nborder-style:dotted;\nborder-color:#53676e;\nborder-left-width:1px;\nborder-right-width:0px;\nborder-top-width:0px;\nborder-bottom-width:0px;\n'
css_render+='margin-left:'+str(j.begin)+'px;\n'
css_render+='height:'+str(self.height)+'px;\n'
css_render+='margin-top:'+str(1+round(self.top))+'px;}\n'
elif j.types=='horizontal_dotted':
css_render+='#'+j.name+'{position:absolute;\nborder-style:dotted;\nborder-color:#53676e;\nborder-left-width:0px;\nborder-right-width:0px;\nborder-top-width:1px;\nborder-bottom-width:0px;\n'
css_render+='margin-left:'+str(self.begin)+'px;\n'
css_render+='height:1px;\n'
css_render+='margin-top:'+str(self.top+j.marge_top)+'px;'
css_render+='width:'+str(self.width)+'px;}\n'
elif j.types=='y_coord':
css_render+='#'+j.name+'{position:absolute;\nborder-style:solid;\nborder-color:#53676e;\nfont-size:9px;\nborder-width:0px;\n'
css_render+='margin-left:'+str(self.width-(len(j.text)*5))+'px;\n' #x6 because this is the appropriate width for our font (9px), maybee need to be parameter
css_render+='margin-top:'+str(self.top+j.marge_top)+'px;}\n'
elif j.types=='vertical':
css_render+='#'+j.name+'{position:absolute;\nborder-style:solid;\nborder-color:#53676e;\nborder-left-width:1px;\nborder-right-width:0px;\nborder-top-width:0px;\nborder-bottom-width:0px;\n'
css_render+='margin-left:'+str((self.width/4)+j.begin)+'px;\n'
css_render+='height:'+str(j.height)+'px;\n'
css_render+='margin-top:'+str(round(self.top)-self.height/2+13)+'px;}\n'
elif j.types=='horizontal':
css_render+='#'+j.name+'{position:absolute;\nborder-style:solid;\nborder-color:#53676e;\nborder-left-width:0px;\nborder-right-width:0px;\nborder-top-width:1px;\nborder-bottom-width:0px;\n'
css_render+='margin-left:'+str((self.width/4)+j.begin)+'px;\n'
css_render+='width:16px;\n'
css_render+='height:1px; \n'
# css_render+='margin-top:'+str(round(self.top)-self.height/2+13)+'px;}\n'
css_render+='margin-top:'+str(round(1+self.top+self.height/2))+'px;}\n'
if self.soon!=[]:
for i in self.soon:
css_render+=i.render_css(y_axis_width,security_index);
return css_render
def addBlock(self,name,block):
self.content.append(Block('activity',name,block[0],block[1],block[2],'',block[3],block[4]))
def addBlockInfo(self,name):
self.content.append(Block('info',name,0,0,0,''))
def addBlockTextY(self,name,text):
self.content.append(Block('text_y',name,0,0,0,text))
def addBlockCoordY(self,name,text,marge_top):
self.content.append(Block('y_coord',name,0,0,0,text,{},marge_top))
def addBlockTextX(self,name,begin,text):
self.content.append(Block('text_x',name,begin,0,0,text))
def addBlockDottedVert(self,name,begin):
self.content.append(Block('vertical_dotted',name,begin,0,0,''))
def addBlockDottedHoriz(self,name,marge_top):
self.content.append(Block('horizontal_dotted',name,0,0,0,'',{},marge_top))
def addBlockVertical(self,name,marge_top,height,marge_left):
self.content.append(Block('vertical',name,marge_left,0,height,'',{},marge_top))
def addBlockHorizontal(self,name,marge_top,height,marge_left):
self.content.append(Block('horizontal',name,marge_left,0,height,'',{},marge_top))
def appendVerticalDottedLine(self,x_axe,width_line,marge_left):
current_marge=marge_left
indic=0
for j in x_axe[1]:
nameblock='Block_vert_'+self.name+str(indic)
self.addBlockDottedVert(nameblock,current_marge)
current_marge+=width_line/float(len(x_axe[1]))
indic+=1
if self.soon!=[]:
for i in self.soon:
i.appendVerticalDottedLine(x_axe,width_line,marge_left)
def buildYtype(self,way,y,level,y_axis_width,height_global_div,height_header,height_axis_x,nbr_line,current_top,space_line,y_max,y_range,y_unity,selection_name,form):
""" used for determining the type of each part of y axis taking into account father and children
'way' is a list whichs allows to determinate if the current block is a type 'soon1' or 'soon2' """
report_url=self.url
if level==0:
name='axis'+str(self.name)
if self.soon!=[]:
y.append(Line('',name,1,y_axis_width,((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),current_top,'',[],'father1'))
else:
y.append(Line('',name,1,y_axis_width,((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),current_top,'',[],'father2'))
if self.paternity==1:
if self.soon!=[]:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+'<a href="portal_selections/foldReport?report_url='+report_url+'&form_id='+form.id+'&list_selection_name='+selection_name+'">-'+self.title+'</a>')
else:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+'<a href="portal_selections/unfoldReport?report_url='+report_url+'&form_id='+form.id+'&list_selection_name='+selection_name+'">+'+self.title+'</a>')
else:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+self.title)
#one constructs the indicators
if y_range!=0:
y[len(y)-1].createIndicators(y_unity,y_range,y_max,height_global_div,height_header,height_axis_x,nbr_line)
if self.soon!=[]:
level+=1
for j in range(0,len(self.soon)):
if j==(len(self.soon)-1):
way.append(1)
else:
way.append(0)
current_top+=((height_global_div-height_header-height_axis_x)/float(nbr_line))
current_top=self.soon[j].buildYtype(way,y,level,y_axis_width,height_global_div,height_header,height_axis_x,nbr_line,current_top,space_line,y_max,y_range,y_unity,selection_name,form)
del way[len(way)-1]
else:
if self.soon!=[]:
name=str(self.name)
for num in way:
name=name+str(num)
y.append(Line('',name,1,y_axis_width,((height_global_div-height_header-height_axis_x)/float(nbr_line)),current_top,'',[],'soon1'))
if self.paternity==1:
if self.soon!=[]:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+'<a href="portal_selections/foldReport?report_url='+report_url+'&form_id='+form.id+'&list_selection_name='+selection_name+'">-'+self.title+'</a>')
else:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+'<a href="portal_selections/unfoldReport?report_url='+report_url+'&form_id='+form.id+'&list_selection_name='+selection_name+'">+'+self.title+'</a>')
else:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+self.title)
# one constructs the stick
y[len(y)-1].addBlockVertical('stickVer'+name,current_top-((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),(height_global_div-height_header-height_axis_x)/float(nbr_line),3*level*6-18) #6 is the width of the standart font, maybe a future parameter
y[len(y)-1].addBlockHorizontal('stickHor'+name,current_top-((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),(height_global_div-height_header-height_axis_x)/float(nbr_line),3*level*6-18)
#one constructs the indicators
if y_range!=0:
y[len(y)-1].createIndicators(y_unity,y_range,y_max,height_global_div,height_header,height_axis_x,nbr_line)
level+=1
for j in range(0,len(self.soon)):
current_top+=((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line))
if j==(len(self.soon)-1):
way.append(1)
else:
way.append(0)
current_top=self.soon[j].buildYtype(way,y,level,y_axis_width,height_global_div,height_header,height_axis_x,nbr_line,current_top,space_line,y_max,y_range,y_unity,selection_name,form)
del way[len(way)-1]
else:
name=str(self.name)
test='true'
for num in way:
name=name+str(num)
if num==0:
test='false'
if test=='true':
y.append(Line('',name,1,y_axis_width,((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),current_top,'',[],'soon2'))
else:
y.append(Line('',name,1,y_axis_width,((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),current_top,'',[],'soon1'))
if self.paternity==1:
if self.soon!=[]:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+'<a href="portal_selections/foldReport?report_url='+report_url+'&form_id='+form.id+'&list_selection_name='+selection_name+'">-'+self.title+'</a>')
else:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+'<a href="portal_selections/unfoldReport?report_url='+report_url+'&form_id='+form.id+'&list_selection_name='+selection_name+'">+'+self.title+'</a>')
else:
y[len(y)-1].addBlockTextY('ytext'+name,str(3*'&nbsp '*level)+self.title)
# one constructs the sticks
y[len(y)-1].addBlockVertical('stickVer'+name,current_top-((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),(height_global_div-height_header-height_axis_x)/float(nbr_line),3*level*6-18)
y[len(y)-1].addBlockHorizontal('stickHor'+name,current_top-((height_global_div-height_header-height_axis_x-((nbr_line-1)*space_line))/float(nbr_line)),(height_global_div-height_header-height_axis_x)/float(nbr_line),3*level*6-18)
#one constructs the indicators
if y_range!=0:
y[len(y)-1].createIndicators(y_unity,y_range,y_max,height_global_div,height_header,height_axis_x,nbr_line)
return current_top
def createIndicators(self,y_unity,y_range,y_max,height_global_div,height_header,height_axis_x,nbr_line):
#one constructs the indicators
maximum_y=y_max
marge_top=0
indic=0
#while maximum_y>=(y_max/float(y_range)):
while maximum_y>=0:
nameblock='Block_'+self.name+str(indic)
text=str('%.2f' %maximum_y)+y_unity
self.addBlockCoordY(nameblock,text,marge_top)
maximum_y=maximum_y-(y_max/float(y_range))
marge_top+=(((height_global_div-height_header-height_axis_x)/float(nbr_line))-10)/y_range
indic+=1
###############################
def appendHorizontalDottedLine(self,marge_top,maximum_y,height_global_div,height_header,height_axis_x,nbr_line,y_range,y_max):
current_top=marge_top
max_y=maximum_y
indic=0
while max_y>=0:
nameblock='Block_hor_'+self.name+str(indic)
self.addBlockDottedHoriz(nameblock,current_top)
max_y=max_y-(y_max/float((y_range-1))) #-1 because we don't want a dotted line on the X-axis
current_top+=(((height_global_div-height_header-height_axis_x)/float(nbr_line))-marge_top)/y_range #10px under the top of the line . float is important here! """
indic+=1
if self.soon!=[]:
for i in self.soon:
i.appendHorizontalDottedLine(marge_top,maximum_y,height_global_div,height_header,height_axis_x,nbr_line,y_range,y_max)
def appendActivityBlock(self,list_block):
indic=0
for data_block in list_block:
self.addBlock('ActivityBlock_'+self.name+'_'+str(indic),data_block)
indic+=1
def createXAxis(self,x_axe,width_line,y_axis_width):
marge_left=y_axis_width
indic1=0
for i in x_axe[1]:
nameblock='block_'+self.name+str(indic1)
self.addBlockTextX(nameblock,marge_left,i)
indic1+=1
marge_left+=width_line/float(len(x_axe[1]))
def addSoon(self,soon):
self.soon.append(soon)
def createLineChild(self,report_section,field,current_top,y_axis_width,width_line,space_line,height_global_div,height_header,height_axis_x,nbr_line,current_index,url):
if len(report_section[current_index].getObject().objectValues())!=0:
paternity=1
else:
paternity=0
soon=Line(title=str(report_section[current_index].getObject().getTitle()),name=self.name+'s'+str(current_index) ,begin=y_axis_width,width=width_line,height=(height_global_div-height_header-height_axis_x)/float(nbr_line),top=current_top,color='#ffffff',paternity=paternity,url=url)
if (current_index+1)<=(len(report_section)-1):
if report_section[current_index+1].getDepth() == 0:
current_top=current_top+((height_global_div-height_header-height_axis_x)/float(nbr_line))+space_line
else:
current_top=current_top+((height_global_div-height_header-height_axis_x)/float(nbr_line))
self.addSoon(soon)
return current_top
def insertActivityBlock(self,line_content,object_start_method_id,object_stop_method_id,x_axe,field):
marge=0
method_start = getattr(line_content,object_start_method_id,None)
method_stop= getattr(line_content,object_stop_method_id,None)
block_begin = method_start()
list_block=[]
if method_stop!=None:
block_stop= method_stop()
else:
block_stop=None
for i in x_axe[0]:
if isinstance(block_begin,DateTime):
comp_test1=block_begin.Date()==i
else:
comp_test1=block_begin==i
if comp_test1==True:
list_block.append([marge,(block_stop-block_begin)/(float(len(x_axe[0]))),0.75,{},0.25]) # 0.75(height) need to be defined
marge+=1/float(len(x_axe[0]))
if list_block!=[]:
self.appendActivityBlock(list_block)
if self.soon!=[]:
script_x=getattr(line_content,field.get_value('data_method'),None)
soon_line=script_x()
indic=0
for s in soon_line:
self.soon[indic].insertActivityBlock(soon_line[indic],object_start_method_id,object_stop_method_id,x_axe,field)
indic+=1
#*************************************************
# class block ***********************************
class Block:
def __init__(self,types,name,begin,width=0,height=0,text='',content={},marge_top=0):
self.types=types
self.name=name
self.begin=begin
self.width=width
self.height=height
self.text=text
self.content=content
self.marge_top=marge_top
# self.color=color need to be implemented in the future!
def render(self,line_width,line_height,portal_url,line_begin,y_axis_width):
"""used for inserting text in a block. one calculates how to organise the space.
one defines a width and height parameter (in pixel) which can be
changed (depends on the size and the font used)
one fetches content which is a dictionnary like
this {'center':'ezrzerezr','topright':'uihiuhiuh',
'topleft':'jnoinoin','botleft':'ioioioioi','botright':'ononono'}
"""
string=''
font_height=10
font_width=6
info=''
#checks if the block starts before the beginning of the line
if ((line_begin+self.begin*line_width) < line_begin):
block_width=self.width+self.begin
#checks if the block is too large for the end of the line. if it is the case, one cuts the block
elif ((self.width*line_width)+(line_begin+self.begin*line_width)>line_width+y_axis_width):
block_width=self.width*line_width-((line_begin+self.begin*line_width+self.width*line_width)-(line_width+y_axis_width))
block_width=block_width/line_width
else:
block_width=self.width
return self.buildInfoBlockBody(line_width,block_width,font_width,line_height) # NEED TO BE TESTED !!!
def render_css(self,line_width,line_height,line,y_axis_width):
string=''
font_height=10
font_width=6
line_begin=line.begin
if ((line_begin+self.begin*line_width) < line_begin): #checks if the block starts before the beginning of the line
block_width=self.width+self.begin
elif ((self.width*line_width)+(line_begin+self.begin*line_width)>line_width+y_axis_width): #checks if the block is too large for the end of the line. if it is the case, one cuts the block
block_width=self.width*line_width-((line_begin+self.begin*line_width+self.width*line_width)-(line_width+y_axis_width))
block_width=block_width/line_width
else:
block_width=self.width
return self.buildInfoBlockCss(font_height,line_height,block_width,line_width) # NEED TO BE TESTED!!
#case with five informations
#************************************************************************
def addInfoCenter(self,info): #add info in the top left corner of a block
self.content['center']=info
def addInfoTopLeft(self,info): #add info in the top left corner of a block
self.content['topleft']=info
def addInfoTopRight(self,info): #add info in the top right corner of a block
self.content['topright']=info
def addInfoBottomLeft(self,info): #add info in the bottom left corner of a block
self.content['botleft']=info
def addInfoBottomRight(self,info): #add info in the bottom right corner of a block
self.content['botright']=info
# ****************************************
def buildInfoBlockBody(self,line_width,block_width,font_width,line_height):
""" create the body of the html for displaying info inside a block"""
displayed1=['center','topright','topleft','botleft','botright']
displayed1=displayed1[0:len(self.content)]
string=''
for i in displayed1:
displayed[i]=0
if len(self.content)==5:
test_height= font_height<=((self.height*line_height)/3)
test_width= ((len(self.content[i])*font_width)<=((block_width*line_width)/3))
if len(self.content)==4 or len(self.content)==3:
test_height= font_height<=((self.height*line_height)/2)
test_width= ((len(self.content[i])*font_width)<=((block_width*line_width)/2))
if len(self.content)==2:
test_height=font_height<=(self.height*line_height)
test_width= (len(self.content[i]*font_width)<=((block_width*line_width)/2))
if len(self.content)==1:
test_height= font_height<=(self.height*line_height)
test_width= (len(self.content[i]*font_width)<=(block_width*line_width))
for i in self.content:
if test_height & test_width:
string+='<div id=\"'+self.name+i+'\">'+ self.content[i]
string+='</div>\n'
displayed[i]=1
#******************checks if we need to add interrogation.png
if ((self.width*line_width>=15) & (self.height*line_height>=15)):
order=displayed1
for i in order:
if displayed[i]==0:
info+=self.content[i]+'|'
for i in order:
if displayed[i]==0:
string+='<div id=\"'+self.name+i+'\" title=\"'+info+'\"><img src=\"'+portal_url+'/images/question.png\" height=\"15\" width=\"15\"> '
string+='</div>\n'
break
#******************
return string
#**************************************************
#*******************************************
def buildInfoBlockCss(self,font_height,line_height,block_width,line_width):
"""use for creating css code when one needs to add info inside a block"""
displayed1=['center','topright','topleft','botleft','botright']
displayed1=displayed1[0:len(self.content)]
string=''
for i in displayed1:
displayed[i]=0
if len(self.content)==5:
test_height= font_height<=((self.height*line_height)/3)
test_width= ((len(self.content[i])*font_width)<=((block_width*line_width)/3))
if len(self.content)==4 or len(self.content)==3:
test_height= font_height<=((self.height*line_height)/2)
test_width= ((len(self.content[i])*font_width)<=((block_width*line_width)/2))
if len(self.content)==2:
test_height=font_height<=(self.height*line_height)
test_width= (len(self.content[i]*font_width)<=((block_width*line_width)/2))
if len(self.content)==1:
test_height= font_height<=(self.height*line_height)
test_width= (len(self.content[i]*font_width)<=(block_width*line_width))
elif len(self.content)==0:
return ''
matrix = {('center',5):{'left':2,'top':2},('center',4):{'left':0,'top':0},
('center',3):{'left':2,'top':2},('center',2):{'left':0,'top':2},
('center',1):{'left':2,'top':2},
('topright',5):{'left':1,'top':0},('topright',4):{'left':1,'top':0},('topright',3):{'left':1,'top':0},('topright',2):{'left':1,'top':2},
('topleft',5):{'left':0,'top':0},('topleft',4):{'left':1,'top':1},('topleft',3):{'left':0,'top':0},
('botleft',5):{'left':0,'top':1},('topleft',4):{'left':0,'top':1},
('botright',5):{'left':1,'top':1}
}
matrix_picture = {('center',5):{'left':2,'top':2},('center',4):{'left':0,'top':0},
('center',3):{'left':2,'top':2},('center',2):{'left':0,'top':2},('center',1):{'left':2,'top':2},
('topright',5):{'left':1,'top':0},('topright',4):{'left':1,'top':0},('topright',3):{'left':1,'top':0},('topright',2):{'left':1,'top':2},
('topleft',5):{'left':0,'top':0},('topleft',4):{'left':1,'top':1},('topleft',3):{'left':0,'top':0},
('botleft',5):{'left':0,'top':1},('topleft',4):{'left':0,'top':1},
('botright',5):{'left':1,'top':1}
}
for i in self.content:
for counter in range(1,5):
matrix_data = matrix[(i,counter)]
left = matrix_data['left']
top= matrix_data['top']
if left == 0:
margin_left=0
else:
margin_left = round(((block_width*line_width)/left)-(font_width*len(self.content[i]))/left)
if top==0:
margin_top=0
else:
margin_top = round(((self.height*line_height)/top)-(font_height/top))
if test_height & test_width:
string+='#'+self.name+i+'{position:absolute;\nmargin-left:'+str(margin_left)+'px;\nmargin-top:'+str(margin_top)+'px;\n}\n'
displayed[i]=1
line.addBlockInfo(self.name+i)
#******************checks if we need to add interrogation.png
if ((block_width*line_width>=15) & (self.height*line_height>=15)):
order=('center','topright','topleft','botleft','botright')
for i in order:
for counter in range(1,5):
matrix_data= matrix [(i,counter)]
left = matrix_data['left']
top = matrix_data['top']
if left == 0:
margin_left=0
else:
margin_left=round(((block_width*line_width)/left)-(15/left))
if top==0:
margin_top=0
else:
margin_top=round(((self.height*line_height)/top)-(15/top))
margin_top = round(((self.height*line_height)/top)-(font_height/top))
if i=='center' & counter==3:
margin_left=round(((block_width*line_width)/left)-(font_width*len(self.content[i]))/left)
margin_top=round(((self.height*line_height)/top)-(font_height/top))
if i=='center' & counter==2:
margin_top=round(((self.height*line_height)/top)-(font_height/top))
string+='#'+self.name+i+'{position:absolute;\nmargin-left:'+str(margin_left)+'px;\nmargin-top:'+str(margin_top)+'0px;\n}'
line.addBlockInfo(self.name+i)
return string
#####################################################
PlanningBoxWidgetInstance = PlanningBoxWidget()
class PlanningBox(ZMIField):
meta_type = "PlanningBox"
widget = PlanningBoxWidgetInstance
validator = PlanningBoxValidatorInstance
security = ClassSecurityInfo()
security.declareProtected('Access contents information', 'get_value')
def get_value(self, id, **kw):
if id == 'default' and kw.get('render_format') in ('list', ):
return self.widget.render(self, self.generate_field_key() , None , kw.get('REQUEST'), render_format=kw.get('render_format'))
else:
return ZMIField.get_value(self, id, **kw)
def render_css(self, value=None, REQUEST=None):
return self.widget.render_css(self,'',value,REQUEST)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment