From f159ee4eaad5a23429ab3f182fe758803ff80901 Mon Sep 17 00:00:00 2001 From: Massimiliano Assante Date: Tue, 12 Mar 2013 17:10:16 +0000 Subject: [PATCH] partially implement text table image git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/reports@71268 82a268e6-3cf1-43bd-a215-b396298e98cf --- .classpath | 4 +- .settings/com.google.gdt.eclipse.core.prefs | 4 +- pom.xml | 2 +- .../client/Presenter/Presenter.java | 5 + .../client/ReportGenerator.java | 2 +- .../client/model/TemplateComponent.java | 55 ++++-- .../client/model/TemplateModel.java | 10 +- .../client/targets/BasicTextArea.java | 59 ++++++- .../client/targets/D4sRichTextarea.java | 62 +++---- .../client/targets/ReportTextArea.java | 87 ++++++---- .../client/targets/SequenceWidget.java | 2 +- .../client/targets/TextTableImage.java | 156 ++++++++++++++++++ .../server/servlet/ReportServiceImpl.java | 2 - src/main/webapp/ReportGenerator.css | 62 +++---- src/main/webapp/images/close.png | Bin 0 -> 1027 bytes src/main/webapp/images/delete.png | Bin 0 -> 715 bytes src/main/webapp/images/heading_1.png | Bin 1064 -> 1002 bytes src/main/webapp/images/heading_2.png | Bin 1091 -> 1029 bytes src/main/webapp/images/heading_3.png | Bin 1085 -> 1023 bytes src/main/webapp/images/heading_4.png | Bin 1083 -> 1021 bytes src/main/webapp/images/heading_5.png | Bin 1080 -> 1018 bytes src/main/webapp/images/title.png | Bin 1075 -> 1080 bytes 22 files changed, 368 insertions(+), 144 deletions(-) create mode 100644 src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/TextTableImage.java create mode 100644 src/main/webapp/images/close.png create mode 100644 src/main/webapp/images/delete.png diff --git a/.classpath b/.classpath index c05ec44..d9b801a 100644 --- a/.classpath +++ b/.classpath @@ -1,6 +1,6 @@ - + @@ -30,5 +30,5 @@ - + diff --git a/.settings/com.google.gdt.eclipse.core.prefs b/.settings/com.google.gdt.eclipse.core.prefs index f00fe43..680411c 100644 --- a/.settings/com.google.gdt.eclipse.core.prefs +++ b/.settings/com.google.gdt.eclipse.core.prefs @@ -1,5 +1,5 @@ -#Thu Mar 07 19:02:40 CET 2013 +#Tue Mar 12 17:50:07 CET 2013 eclipse.preferences.version=1 -lastWarOutDir=/Users/massi/Documents/workspace/reports/target/reports-4.0.3-SNAPSHOT +lastWarOutDir=/Users/massi/Documents/workspace/reports/target/reports-4.0.4-SNAPSHOT warSrcDir=src/main/webapp warSrcDirIsOutput=false diff --git a/pom.xml b/pom.xml index 0f6a882..92e713e 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ org.gcube.portlets.user reports war - 4.0.3-SNAPSHOT + 4.0.4-SNAPSHOT gCube Reports Portlet gCube Reports Portlet. diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java index 42d769e..f46adb2 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/Presenter/Presenter.java @@ -44,6 +44,7 @@ import org.gcube.portlets.user.reportgenerator.client.targets.GenericTable; import org.gcube.portlets.user.reportgenerator.client.targets.GroupingDelimiterArea; import org.gcube.portlets.user.reportgenerator.client.targets.ReportTextArea; import org.gcube.portlets.user.reportgenerator.client.targets.TSArea; +import org.gcube.portlets.user.reportgenerator.client.targets.TextTableImage; import org.gcube.portlets.user.reportgenerator.shared.SessionInfo; import org.gcube.portlets.user.reportgenerator.shared.UserBean; @@ -1048,6 +1049,10 @@ public class Presenter { ClientRepeatableSequence rps = (ClientRepeatableSequence) component.getContent(); wp.addComponentToLayout(rps, component.isDoubleColLayout()); break; + case BODY_TABLE_IMAGE: + TextTableImage tti = (TextTableImage) component.getContent(); + wp.addComponentToLayout(tti, component.isDoubleColLayout()); + break; } } } diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java index ac64802..99ab58e 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/ReportGenerator.java @@ -135,7 +135,7 @@ public class ReportGenerator implements EntryPoint { mainLayout.add(cellPanel); divHidden.setStyleName("d4sFrame"); - divHidden.setWidth("500"); + divHidden.setWidth("750px"); divHidden.setStyleName("d4sRichTextArea"); divHidden.addStyleName("setVisibilityOff"); divHidden.addStyleName("hasRichTextToolbar"); diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateComponent.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateComponent.java index 469018a..e8cc434 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateComponent.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateComponent.java @@ -25,6 +25,7 @@ import org.gcube.portlets.user.reportgenerator.client.targets.GroupingDelimiterA import org.gcube.portlets.user.reportgenerator.client.targets.GroupingInnerArea; import org.gcube.portlets.user.reportgenerator.client.targets.ReportTextArea; import org.gcube.portlets.user.reportgenerator.client.targets.TSArea; +import org.gcube.portlets.user.reportgenerator.client.targets.TextTableImage; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Unit; @@ -138,14 +139,16 @@ public class TemplateComponent { this.doubleColLayout = false; this.metadata = new LinkedList(); } - + /** * create a template component which is displayable (create an actual Widget in the content field) * @param myModel the model * @param sc the serialiazble to convert * @param presenter . + * @param showClose + * @param owner needed only for the TextTableImage case and because im in hurry */ - public TemplateComponent(TemplateModel myModel, BasicComponent sc, Presenter presenter) { + public TemplateComponent(TemplateModel myModel, BasicComponent sc, Presenter presenter, boolean showClose, TextTableImage owner) { this.myModel = myModel; // //Coords start = new Coords(x, y); @@ -161,7 +164,7 @@ public class TemplateComponent { this.doubleColLayout = sc.isDoubleColLayout(); this.locked = sc.isLocked(); this.metadata = sc.getMetadata(); - + switch (sc.getType()) { case DYNA_IMAGE: ClientImage dp = new ClientImage(sc, presenter, sc.getWidth(), sc.getHeight()); @@ -184,7 +187,7 @@ public class TemplateComponent { this.content = area; } else { - BasicTextArea bToAdd = new BasicTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, 25, getUserComments() != null); + BasicTextArea bToAdd = new BasicTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, 25, getUserComments() != null, showClose); bToAdd.setText((String) sc.getPossibleContent()); this.content = bToAdd; } @@ -201,7 +204,7 @@ public class TemplateComponent { } else { height = 40; - D4sRichTextarea ta = new D4sRichTextarea(sc.getType(), presenter, sc.getX(), sc.getY(),width, height, getUserComments() != null); + D4sRichTextarea ta = new D4sRichTextarea(sc.getType(), presenter, sc.getX(), sc.getY(),width, height, getUserComments() != null, showClose, owner); ta.setHTML((String) sc.getPossibleContent()); //ta.setStyleName("cw-RichText"); ta.setPixelSize(width, height); @@ -210,17 +213,17 @@ public class TemplateComponent { this.setLocked(sc.isLocked()); break; case TOC: - ReportTextArea dp2 = new ReportTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, height, getUserComments() != null); + ReportTextArea dp2 = new ReportTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, height, getUserComments() != null, showClose); dp2.addStyleName("tocArea"); this.content = dp2; break; case BIBLIO: - ReportTextArea dp3 = new ReportTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, height, getUserComments() != null); + ReportTextArea dp3 = new ReportTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, height, getUserComments() != null, showClose); dp3.addStyleName("biblioArea"); this.content = dp3; break; case PAGEBREAK: - ReportTextArea dp4 = new ReportTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, height, getUserComments() != null); + ReportTextArea dp4 = new ReportTextArea(sc.getType(), presenter, sc.getX(), sc.getY(), width, height, getUserComments() != null, showClose); dp4.addStyleName("pagebreak"); this.content = dp4; break; @@ -294,12 +297,22 @@ public class TemplateComponent { case REPEAT_SEQUENCE: GWT.log("FOUND SEQUENCE trying getGroup"); RepeatableSequence repeatableSequence = (RepeatableSequence) sc.getPossibleContent(); - + GWT.log("getGroup: " + repeatableSequence.toString()); - + ClientRepeatableSequence rps = new ClientRepeatableSequence(presenter, repeatableSequence); this.content = rps; break; + case BODY_TABLE_IMAGE: + TextTableImage tti = null; + if (sc.getPossibleContent() == null) { //is is a template + tti = new TextTableImage(presenter, true); + } else { + RepeatableSequence seq = (RepeatableSequence) sc.getPossibleContent(); + tti = new TextTableImage(presenter, seq); + } + this.content = tti; + break; } } /** @@ -361,7 +374,7 @@ public class TemplateComponent { case TITLE: if (this.isLocked()) { content = ((HTML) this.content).getText(); - + } else content = ((BasicTextArea) this.content).getText(); @@ -395,12 +408,17 @@ public class TemplateComponent { RepeatableSequence toStore = new RepeatableSequence(getSerializableSequence(repSeq), height); content = toStore; break; + case BODY_TABLE_IMAGE: + TextTableImage tti = (TextTableImage) this.content; + RepeatableSequence toSave = new RepeatableSequence(getSerializableSequence(tti), height); + content = toSave; + break; } return new BasicComponent(x, y, width, height, templatePage, type, idInBasket, "param empty", content, this.doubleColLayout, isLocked(), metadata); } /** - * this method constructs a SerializableRepeatableSequence sequence that can be serializable + * this method constructs a RepeatableSequence sequence that can be serializable from the ClientRepeatableSequence * @param repSeq * @return */ @@ -411,6 +429,19 @@ public class TemplateComponent { } return sComps; } + + /** + * this method constructs a Sequence that can be serializable from the TextTableImage Widget + * @param repSeq + * @return + */ + private ArrayList getSerializableSequence(TextTableImage seq) { + ArrayList sComps = new ArrayList(); + for (TemplateComponent tc : seq.getAddedComponents()) { + sComps.add(tc.getSerializable()); + } + return sComps; + } /** * @return . diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java index 0733da4..3b6d7f6 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/model/TemplateModel.java @@ -200,7 +200,7 @@ public class TemplateModel { BasicComponent references = new BasicComponent(0, 0,TEMPLATE_WIDTH - 50, 35, totalPages, ComponentType.HEADING_2, "", "REFERENCES", false, true, singleSection.getAllMetadata()); - TemplateComponent referencesTC = new TemplateComponent(this, references, presenter); + TemplateComponent referencesTC = new TemplateComponent(this, references, presenter, false, null); singleSection.addComponent(referencesTC); sections.put(""+totalPages, singleSection); @@ -216,11 +216,11 @@ public class TemplateModel { TemplateSection singleSection = getSection(totalPages); BasicComponent entry = new BasicComponent(0, 0,TEMPLATE_WIDTH - 50, 35, totalPages, ComponentType.HEADING_2, "", "Bibliographic Entry", false, true, singleSection.getAllMetadata()); - TemplateComponent entryTC = new TemplateComponent(this, entry, presenter); + TemplateComponent entryTC = new TemplateComponent(this, entry, presenter, false, null); singleSection.addComponent(entryTC); BasicComponent entryText = new BasicComponent(0, 0,TEMPLATE_WIDTH - 50, 35, totalPages, ComponentType.BODY, "", citation, false, false, singleSection.getAllMetadata()); - TemplateComponent entryTextTC = new TemplateComponent(this, entryText, presenter); + TemplateComponent entryTextTC = new TemplateComponent(this, entryText, presenter, false, null); singleSection.addComponent(entryTextTC); storeInSession(); } @@ -295,7 +295,7 @@ public class TemplateModel { List myTemplateSection = new Vector(); for (BasicComponent sc : serialazableSection.getComponents()) { //for each page component - myTemplateSection.add(new TemplateComponent(this, sc, presenter)); + myTemplateSection.add(new TemplateComponent(this, sc, presenter, false, null)); } //TODO: load also metadata GWT.log("Section Metadata:"+serialazableSection.getMetadata().size(), null); @@ -321,7 +321,7 @@ public class TemplateModel { BasicSection toImport = toLoad.getSections().get(sectionNoToimport-1); List myTemplateSection = new Vector(); for (BasicComponent sc : toImport.getComponents()) { //for each page component - myTemplateSection.add(new TemplateComponent(this, sc, presenter)); + myTemplateSection.add(new TemplateComponent(this, sc, presenter, false, null)); } //TODO: load also metadata GWT.log("Section Metadata:"+toImport.getMetadata().size(), null); diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/BasicTextArea.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/BasicTextArea.java index e8fa8fb..90f92ec 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/BasicTextArea.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/BasicTextArea.java @@ -4,14 +4,16 @@ import org.gcube.portlets.d4sreporting.common.shared.ComponentType; import org.gcube.portlets.user.reportgenerator.client.ReportGenerator; import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter; -import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.event.dom.client.MouseDownEvent; +import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasVerticalAlignment; -import com.google.gwt.user.client.ui.TextArea; +import com.google.gwt.user.client.ui.RichTextArea; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; /** @@ -21,19 +23,21 @@ import com.google.gwt.user.client.ui.Widget; * @version July 2011 (3.0) */ public class BasicTextArea extends ReportTextArea { - private TextArea textArea = new TextArea(); + private RichTextArea textArea = new RichTextArea(); private VerticalPanel myPanel; - private Presenter presenter; int currHeight = 0; + - public BasicTextArea(ComponentType type, final Presenter presenter, int left, int top, int width, final int height, boolean hasComments) { - super(type, presenter, left, top, width, height, hasComments); - this.presenter = presenter; + + public BasicTextArea(ComponentType type, final Presenter presenter, int left, int top, final int width, final int height, boolean hasComments, boolean showClose) { + super(type, presenter, left, top, width, height, hasComments, showClose); + currHeight = height; myPanel = getResizablePanel(); textArea.setPixelSize(width, height); + textArea.getElement().getStyle().setMarginTop(-4, Unit.PX); //this is needed because the richtextarea has margin 8px and a not able to modify it via css textArea.addMouseOutHandler(new MouseOutHandler() { @@ -85,6 +89,33 @@ public class BasicTextArea extends ReportTextArea { } }); + + textArea.addKeyUpHandler(new KeyUpHandler() { + public void onKeyUp(KeyUpEvent event) { + HTML div = ReportGenerator.get().getDivHidden(); + div.setHTML(textArea.getHTML()); + int newHeight = div.getOffsetHeight(); + if (newHeight > currHeight) { + resizePanel(width, newHeight); + presenter.resizeTemplateComponentInModel(myInstance, width, newHeight); + currHeight = newHeight; + } + } + }); + + textArea.addMouseDownHandler(new MouseDownHandler() { + public void onMouseDown(MouseDownEvent event) { + HTML div = ReportGenerator.get().getDivHidden(); + div.setHTML(textArea.getHTML()); + int newHeight = div.getOffsetHeight(); + if (newHeight > currHeight) { + resizePanel(width, newHeight); + presenter.resizeTemplateComponentInModel(myInstance, width, newHeight); + currHeight = newHeight; + } + } + }); + } public String getText() { return textArea.getText(); @@ -93,5 +124,19 @@ public class BasicTextArea extends ReportTextArea { textArea.setText(text); } + /** + * used to resize the panel + * @param width w + * @param height h + */ + @Override + public void resizePanel(int width, int height) { + if (height > 25) { + mainPanel.setPixelSize(width, height); + resizablePanel.setPixelSize(width, height); + textArea.setPixelSize(width-4, height); + currHeight = height; + } + } } diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/D4sRichTextarea.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/D4sRichTextarea.java index 6d7c843..4670cf5 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/D4sRichTextarea.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/D4sRichTextarea.java @@ -14,6 +14,7 @@ import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.user.client.Event; +import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.RichTextArea; @@ -48,6 +49,8 @@ public class D4sRichTextarea extends ReportTextArea { */ public D4sRichTextarea() {} + private TextTableImage owner; + /** * * @param presenter . @@ -57,8 +60,10 @@ public class D4sRichTextarea extends ReportTextArea { * @param height . * @param type . */ - public D4sRichTextarea(ComponentType type, final Presenter presenter, int left, int top, int width, final int height, boolean hasComments) { - super(type, presenter, left, top, width, height, hasComments); + public D4sRichTextarea(ComponentType type, final Presenter presenter, int left, int top, final int width, + final int height, boolean hasComments, boolean showClose, TextTableImage owner) { + super(type, presenter, left, top, width, height, hasComments, showClose); + this.owner = owner; currHeight = height; myPanel = getResizablePanel(); @@ -91,16 +96,16 @@ public class D4sRichTextarea extends ReportTextArea { presenter.enableTextToolBar(area); presenter.enableBiblioEntry(area); firstClick = false; - ReportGenerator.get().getDivHidden().setPixelSize(area.getOffsetWidth(), -1); + ReportGenerator.get().getDivHidden().setPixelSize(width, -1); } HTML div = ReportGenerator.get().getDivHidden(); div.setHTML(area.getHTML()); int newHeight = div.getOffsetHeight()+20 ; if (newHeight > height-10 && newHeight != currHeight) { presenter.shiftComponentsByTextArea(myInstance.top, newHeight - currHeight); - resizePanel(myPanel.getOffsetWidth(), div.getOffsetHeight()); + resizePanel(width, div.getOffsetHeight()); //Window.alert("myInstance.top: " + myInstance.top); - presenter.resizeTemplateComponentInModel(myInstance, myPanel.getOffsetWidth(), newHeight); + presenter.resizeTemplateComponentInModel(myInstance, width, newHeight); } } }); @@ -112,42 +117,7 @@ public class D4sRichTextarea extends ReportTextArea { } }); - //TODO: aggiorna - // area.addKeyDownHandler(new KeyDownHandler() { - // public void onKeyDown(KeyDownEvent event) { - //// if (event.isAnyModifierKeyDown() && event.getNativeKeyCode() == 86) { //event.getNativeKeyCode() == 86 is the V (to avoid ctrl V or cmd V) - //// MessageBox.show(new MessageBoxConfig() { - //// { - //// setTitle("Paste operation"); - //// setMsg("Please enter your text here (PLAIN)"); - //// setWidth(500); - //// setButtons(MessageBox.OKCANCEL); - //// setMultiline(true); - //// setCallback(new MessageBox.PromptCallback() { - //// public void execute(String btnID, String text) { - //// if (btnID.compareTo("ok") == 0) { - //// area.setText(text); - //// - //// //resize if needed - //// HTML div = ReportGenerator.get().getDivHidden(); - //// //GWT.log("element.getHTML():\n" + area.getHTML(), null); - //// div.setHTML(area.getHTML()); - //// int newHeight = div.getOffsetHeight()+20 ; - //// if (newHeight > height-10 && newHeight != currHeight) { - //// resizePanel(myPanel.getOffsetWidth(), div.getOffsetHeight()); - //// } - //// } - //// - //// } - //// }); - //// } - //// }); - // event.stopPropagation(); - // event.preventDefault(); - // } - // - // } - // }); + area.addKeyUpHandler(new KeyUpHandler() { public void onKeyUp(KeyUpEvent event) { HTML div = ReportGenerator.get().getDivHidden(); @@ -174,7 +144,7 @@ public class D4sRichTextarea extends ReportTextArea { mainPanel.setPixelSize(width, height+20); resizablePanel.setPixelSize(width, height+20); mainPanel.setWidgetPosition(topPanel, width-30 , 0); - area.setPixelSize(width-4, height+20); + area.setPixelSize(width, height+20); currHeight = height + 20; } } @@ -208,4 +178,12 @@ public class D4sRichTextarea extends ReportTextArea { public void setFirstClick(boolean firstClick) { this.firstClick = firstClick; } + + @Override + public void removeTemplateComponent() { + if (owner != null) { + owner.removeFromParent(this); + removeFromParent(); + } + } } diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/ReportTextArea.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/ReportTextArea.java index bd729e2..864c0d6 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/ReportTextArea.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/ReportTextArea.java @@ -1,6 +1,7 @@ package org.gcube.portlets.user.reportgenerator.client.targets; import org.gcube.portlets.d4sreporting.common.client.ImageConstants; +import org.gcube.portlets.d4sreporting.common.client.uicomponents.ReportUIComponent; import org.gcube.portlets.d4sreporting.common.shared.ComponentType; import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter; import org.gcube.portlets.user.reportgenerator.client.dialog.CommentDialog; @@ -9,6 +10,7 @@ import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.AbsolutePanel; import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; @@ -40,14 +42,16 @@ public class ReportTextArea extends Composite { private Presenter presenter; private ComponentType type; - + protected AbsolutePanel mainPanel; protected HorizontalPanel topPanel; protected VerticalPanel resizablePanel; - + protected Image commentImage; + + private HTML closeImage = new HTML(); /** * * @return . @@ -74,9 +78,9 @@ public class ReportTextArea extends Composite { * @param height . * @param type a */ - public ReportTextArea(ComponentType type, final Presenter presenter, int left, int top, int width, int height, boolean hasComments) { + public ReportTextArea(ComponentType type, final Presenter presenter, int left, int top, int width, int height, boolean hasComments, boolean isRemovable) { myInstance = this; - + this.type = type; this.presenter = presenter; @@ -94,11 +98,11 @@ public class ReportTextArea extends Composite { topPanel.setPixelSize(30, 15); resizablePanel.setPixelSize(width, height); - + commentImage = new Image((hasComments) ? ImageConstants.IMAGE_COMMENTS : ImageConstants.IMAGE_COMMENTS_GRAY); commentImage.setTitle("Show user comments"); topPanel.add(commentImage); - + commentImage.setStyleName("selectable"); commentImage.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { @@ -111,16 +115,33 @@ public class ReportTextArea extends Composite { dlg.show(); } }); - + topPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT); mainPanel.add(resizablePanel, 0, 0); - mainPanel.add(topPanel, width-18, 0); + mainPanel.add(topPanel, width-30, 0); mainPanel.setStyleName("d4sFrame"); initWidget(mainPanel); - } + if (isRemovable) { + closeImage.setHeight("15px"); + closeImage.setStyleName("closeImage"); + closeImage.setTitle("Click to remove"); + topPanel.add(closeImage); + } + + closeImage.addClickHandler(new ClickHandler() { + public void onClick(ClickEvent event) { + remove(); + } + }); + } + private void remove() { + removeTemplateComponent(); + } + + public void removeTemplateComponent() { } /** * * @return . @@ -137,7 +158,7 @@ public class ReportTextArea extends Composite { this.type = type; } - + /** * used to resize the panel * @param width w @@ -150,8 +171,8 @@ public class ReportTextArea extends Composite { mainPanel.setWidgetPosition(topPanel, width-15, 0); } } - - + + /*** * * @param height g @@ -173,8 +194,8 @@ public class ReportTextArea extends Composite { public void repositionMyPanel(int left, int top) { //mainPanel.setWidgetPosition(resizablePanel, left, top); } - - + + /** * @return . */ @@ -215,7 +236,7 @@ public class ReportTextArea extends Composite { return presenter; } - + /** * * @return . @@ -223,7 +244,7 @@ public class ReportTextArea extends Composite { public ReportTextArea getMyInstance() { return myInstance; } - + /** * * @param myInstance . @@ -238,23 +259,23 @@ public class ReportTextArea extends Composite { public void addCommentView() { commentImage.setUrl(ImageConstants.IMAGE_COMMENTS); } - + public void showComment(String comment) { -// final Window window = new Window(); -// window.setTitle(""); -// window.setMaximizable(true); -// window.setResizable(true); -// window.setLayout(new FitLayout()); -// window.setWidth(200); -// window.setHeight(100); -// window.setModal(false); -// -// Panel windowPanel = new Panel(); -// windowPanel.setBaseCls("comment-popup"); -// windowPanel.setHtml(comment); -// windowPanel.setShadow(true); -// window.add(windowPanel); -// window.setPosition(commentImage.getAbsoluteLeft()+25, commentImage.getAbsoluteTop()); -// window.show(); + // final Window window = new Window(); + // window.setTitle(""); + // window.setMaximizable(true); + // window.setResizable(true); + // window.setLayout(new FitLayout()); + // window.setWidth(200); + // window.setHeight(100); + // window.setModal(false); + // + // Panel windowPanel = new Panel(); + // windowPanel.setBaseCls("comment-popup"); + // windowPanel.setHtml(comment); + // windowPanel.setShadow(true); + // window.add(windowPanel); + // window.setPosition(commentImage.getAbsoluteLeft()+25, commentImage.getAbsoluteTop()); + // window.show(); } } diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/SequenceWidget.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/SequenceWidget.java index 86e434f..d5b9b3c 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/SequenceWidget.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/SequenceWidget.java @@ -62,7 +62,7 @@ public class SequenceWidget extends Composite { sComp.setPossibleContent(""); sComp.setMetadata(new ArrayList()); } - add(new TemplateComponent(p.getModel(), sComp, p)); + add(new TemplateComponent(p.getModel(), sComp, p, false, null)); } initWidget(myPanel); diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/TextTableImage.java b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/TextTableImage.java new file mode 100644 index 0000000..36bdd2b --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/client/targets/TextTableImage.java @@ -0,0 +1,156 @@ +package org.gcube.portlets.user.reportgenerator.client.targets; + +import java.util.ArrayList; + +import org.gcube.portlets.d4sreporting.common.shared.BasicComponent; +import org.gcube.portlets.d4sreporting.common.shared.ComponentType; +import org.gcube.portlets.d4sreporting.common.shared.RepeatableSequence; +import org.gcube.portlets.user.reportgenerator.client.Presenter.Presenter; +import org.gcube.portlets.user.reportgenerator.client.model.TemplateComponent; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FocusPanel; +import com.google.gwt.user.client.ui.HasHorizontalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.VerticalPanel; +/** + * + * @author Massimiliano Assante ISTI-CNR + * + */ +public class TextTableImage extends Composite { + + public static final int DEFAULT_HEIGHT = 100; + public static final int DEFAULT_WIDTH = 700; + + private FocusPanel focusPanel = new FocusPanel(); + private VerticalPanel mainPanel = new VerticalPanel(); + private HorizontalPanel controlPanel; + + private Button addTextB = new Button("Add Text"); + private Button addImageB = new Button("Add Image"); + private Button addTableB = new Button("Add Table"); + private Presenter presenter; + private ArrayList addedComponents = new ArrayList(); + + /** + * constructor to be used when reading from a template + * @param presenter + */ + public TextTableImage(Presenter presenter, boolean isFromTemplate) { + this.presenter = presenter; + mainPanel.setStyleName("imageTableTextPanel"); + controlPanel = getControlPanel(); + controlPanel.setStyleName("imageTableTextControlPanel"); + mainPanel.add(controlPanel); + + focusPanel.add(mainPanel); + initWidget(focusPanel); + + if (isFromTemplate) { + int height = 40; + D4sRichTextarea firstText = new D4sRichTextarea(ComponentType.BODY, presenter, 0, 0, DEFAULT_WIDTH, height, false, true, this); + firstText.setPixelSize(DEFAULT_WIDTH, height); + mainPanel.add(firstText); + //construct the first component and add it + TemplateComponent toAdd = new TemplateComponent(presenter.getModel(), 0, 0, DEFAULT_WIDTH, height, + presenter.getModel().getCurrentPage(), ComponentType.BODY, "", firstText); + add(toAdd); + } + } + /** + * constructor to be used when reading from a report + * @param presenter + * @param sRS + */ + public TextTableImage(Presenter presenter, RepeatableSequence sRS) { + this(presenter, false); + if (sRS != null && sRS.getGroupedComponents().size() > 0) { + for (BasicComponent sComp : sRS.getGroupedComponents()) { + add(new TemplateComponent(presenter.getModel(), sComp, presenter, true, this)); + } + } + } + public void add(TemplateComponent toAdd) { + addedComponents.add(toAdd); + GWT.log("ToAdd= getType " + toAdd.getType()); + mainPanel.add(toAdd.getContent()); + } + + private void addNewText() { + int height = 40; + D4sRichTextarea text = new D4sRichTextarea(ComponentType.BODY, presenter, 0, 0, DEFAULT_WIDTH, height, false, true, this); + text.setPixelSize(DEFAULT_WIDTH, height); + TemplateComponent toAdd = new TemplateComponent(presenter.getModel(), 0, 0, DEFAULT_WIDTH, height, + presenter.getModel().getCurrentPage(), ComponentType.BODY, "", text); + add(toAdd); + } + + private void addNewTable() { + + } + /** + * + * @return + */ + private HorizontalPanel getControlPanel() { + final HorizontalPanel toReturn = new HorizontalPanel(); + + addTextB.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + addNewText(); + } + }); + + addImageB.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + + } + }); + + addTableB.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + } + }); + toReturn.setSpacing(3); + + toReturn.add(addTextB); + toReturn.add(addTableB); + toReturn.add(addImageB); + + + //set style for buttons + for (int i = 0; i < toReturn.getWidgetCount(); i++) { + if (toReturn.getWidget(i) instanceof Button) { + Button b = (Button) toReturn.getWidget(i); + b.addStyleName("tableButton"); + } + } + return toReturn; + } + + public ArrayList getAddedComponents() { + return addedComponents; + } + + public void removeFromParent(D4sRichTextarea d4sRichTextarea) { + for (TemplateComponent tc : addedComponents) { + if (tc.getType() == ComponentType.BODY) { + D4sRichTextarea toCheck = (D4sRichTextarea) tc.getContent(); + if (toCheck.equals(d4sRichTextarea)) { + addedComponents.remove(tc); + break; + } + } + } + + } + +} diff --git a/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java b/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java index f15cf08..53d6d9c 100644 --- a/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/reportgenerator/server/servlet/ReportServiceImpl.java @@ -878,8 +878,6 @@ public class ReportServiceImpl extends RemoteServiceServlet implements ReportSe ASLSession d4Session = getASLSession(); d4Session.setAttribute(CURRENT_REPORT_INSTANCE, model); - System.out.println("SAVED"); - Vector sections = model.getSections(); for (BasicSection section : sections) { for (BasicComponent component : section.getComponents()) { diff --git a/src/main/webapp/ReportGenerator.css b/src/main/webapp/ReportGenerator.css index 0a2bb5e..552f4cc 100644 --- a/src/main/webapp/ReportGenerator.css +++ b/src/main/webapp/ReportGenerator.css @@ -1,5 +1,21 @@ @import url('reports/old-dialog.css'); +.closeImage { + background: url(images/close.png) 0px 0px no-repeat; + height: 15px; + width: 15px; +} + +.closeImage:hover { + background: url(images/close.png) 0px -16px no-repeat; + cursor: pointer; + cursor: hand; +} + +.closeImage:active { + background: url(images/close.png) 0px -32px no-repeat; +} + .deleteEntryButton { background-image: none !important; background-repeat: none !important; @@ -40,6 +56,16 @@ width: 600px; } +.imageTableTextPanel { + background-color: transparent; + margin: 8px 0px; +} + +.imageTableTextControlPanel { + margin-top: 5px; +} + + .imageWrapperPanel { background-color: transparent; border-bottom: 2px dashed #FFF; @@ -452,8 +478,6 @@ tableBorder td { .setVisibilityOn { margin-top: 1px; visibility: visible; - cursor: pointer; - cursor: hand; } .templateFrame { @@ -662,38 +686,4 @@ gwt-MenuBar { .cw-RichText { border: 1px solid #BBBBBB; border-spacing: 0px; -} - -/* *********** FANCY FILE UPLOAD **************/ -.fancyfileupload-pending { - font-family: arial; - font-size: 10px; - background: orange; - width: 200px; -} - -.fancyfileupload-loading { - font-family: arial; - font-size: 10px; - background: orange; - width: 200px; -} - -.fancyfileupload-loaded { - font-family: arial; - font-size: 10px; - background: lightgreen; - width: 200px; -} - -.fancyfileupload-failed { - font-family: arial; - font-size: 10px; - background: blue; - width: 200px; -} - -/* *********** END FANCY FILE UPLOAD **************/ -.droppingArea-Text { - border: 1px inset black; } \ No newline at end of file diff --git a/src/main/webapp/images/close.png b/src/main/webapp/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..4f60bae929460d237eae962405008e8e297a4f9b GIT binary patch literal 1027 zcmaJ=O=#3W6b`M3mKG2GfW^a*dQfrm*WFDMy4Kyz#s->o*4Oh@KZWunKvKE?xKy!>4ScZnRH2(~a zQdBQ(S8KSYPsk>67$e3oq2m!YMU9Syo?*^H45r|W?Plmt57%g5TN(O9O6PPh59{{$ zvJWfE#j3eHYf2V9b_9%uG7)efHbCgixq%#J=%%hr&as=NK@);!GxSDMHN6D#$cG@s za0!!3b0Ez#{BTkf#lt}0c#h=+mKPGdC=UxV$AQ*IlW4v*EteIw6^mFIx{k3YvuvZ$ zU>d^=@@H6HlB8He5E2BD2$o!Igb6noYAYx(Fn!y@HgZ9%XiT96oS{jk8zneiN7fBm z*F-Li4GoXw87?lV4b=7jLmj7s4saQ6=KD|Kpt|HiwhRNb;G3jz(?fA6PtN<$z{sy6 zG}pexQXOFw)R71Bl@!no({^LKiPv>ma|3L+Ce)M+O%xd0w&WC_74m#iOsi6o=L>?A z%Bh94n#`#JpA%CfZLWgM1qZsg&9yeUBVD=iC^#O8tU%vhgqG?f2Q*8T?e4jxy6UyK zR`*=eUAZhthK(EhSEJi5GClFJGq%L&3_f(pwEJYN#jlG!-3jWU=}Z|T>f!&_3ejC z`|qW%+?d#TKX~0ZyB2Lx_su^MYIEA)Ev52kK9nB(I{D_#sc+Hu^XIaACaM0LJ!izH Q*A5bSN-GqVySd5LKcsg}2LJ#7 literal 0 HcmV?d00001 diff --git a/src/main/webapp/images/delete.png b/src/main/webapp/images/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..08f249365afd29594b51210c6e21ba253897505d GIT binary patch literal 715 zcmV;+0yO=JP)C4}Mrzlg<+1Y8PEBfUp0jJpx4B>@E+cy3`^(Gw`Mf+2&yxZm<$to~Vpgvg&QKNR z_f#1(r6svZt%iF?s+n<8X?B&!h3g9Dbb8_=MX}!;HiQSAh`bp^WMl~Z-44teO7W_Y zV4thSL{h;rJY7!l3%5J4H1!tIzB`Dv+YxO(haWeausGZYkI8^hWj6mzo=L0{%;yxzh{5!Htr?51 zvG|W62MzC8BZ76hRpCyO2zOn<%e)K>NHge!-~)Ap33OdWw6hsLYbCxGNt0%wk_2z7 zfyYvXheSG)5HRK1VB~%mq7Dmurw#bi@hEcOr3&G1ZiF*$M=&9nB#VNf&Q^r$4G5kp zTURh&s)E0%5&hyVD}sp<72~zmAY`Y(9aqO6CXF%=zFHGzO-A&I(pE}v70YQxCPJ{Y z4L+?5-crdLn3ZRPEs!A4ehEY3ZRpL~w9>@aMN+{F4dI@v&>(QDHQum!mG~E^$OS8l z!7?%Uwib*ROP67Hw`ika)gX-(8Ia`-u_IEhxG7U<13kSsMW+$lbb2dUMm5p6pa}cjgA+U$^mJ^AjD?&bdi)8~y+Q002ovPDHLkV1g8IMc@Dc literal 0 HcmV?d00001 diff --git a/src/main/webapp/images/heading_1.png b/src/main/webapp/images/heading_1.png index 365d91a0936426f1ccc1a8c22fd40d7728d48db4..b5ca1a6a994b86d676bcbebdf9121e8757e817ea 100644 GIT binary patch delta 313 zcmZ3%@rr$dIF}p;8v_G_nclsp6BRWWl{R{*Gfuw4s5Ci?F?;eZCf&)^OwtN21|}{B zE+$SE#wN~&hOS1I=B@@#mXEa?U-a>ikxvOdd6fB12xGKmm(#F;*y}$ zG^>>S;OXk;vd$@?2>^#!R>}YX delta 398 zcmaFGzJg8jkGftkxm@+wwQM10l*VoFwC^J1XFEPg@ zKe;qFHLt|e#a5{zw?Ho?GsVil%)-FX(A>np+z7}tG_*7{uynI@bu%z`u`o4paZ*wM zssx&WO|PkwrHP@lxs#crv5BFftC5A7fw{AZnVFM`xudJ4nIll|WL+jn1*kelTP70QpoVgWIbjl4xwEay@5d$F}Z?SCSVe4{p0fuhDHa}+WhBe z*(qF0*rb~fmtnNyQA6t`1%;bTPZSokr79aNR%DkpbUa}ZCEpWekj2RC(7?!0HD7Tm TzowK9&@cv1S3j3^P6_je&u|Oz+;)iHaJGN*le@87JRiRGOT{m_2zHlkVhdCTRr|R})8P z0}BHSV^ae|Lsuh9b5{c=OG_6=XA5Tw12gBzc1$ubMTR&PJ!3M6aWOD)F>o<)u`o7q z#%7X|LUBn@YMNC_esXDUYF>$_i>*>cZh>A(W{MS5uPZLSlZ%+0I3{|F=>q*zIe8DW zOrfsC)`TleN(|gRAI<;q%t(vNIONbH!J}|G@D1~XhYHMz60=)HA{|a_WtL{&aY!P* zK=84)Sj|C)6Gll*J!=%2T+MtRHHaME$R=p`(9bI_K_)k}C(0m;k=dbvkzv;(UD1vi Sn%jZ4F?hQAxvXucp-l$oBHmzd*{ zpIn-onpfiKVyjeD#)yTrkz}(ry%*@He+|kw2%n_(}vM!UP0#uzDE_IWC zF&a)@%%mSf*fGT=L8)n0DP(wLvL3S&$MIsODqv6*Pp)8=$!=iPF*tVrhjGHJ%7vWF zhDinuI_?|!9om|CS`u@_f>Ib2uk+=|Jm5;MIq2H6KH>u_v*PIvPNPjt9AY<3I+=rb vj!U^5X|dLEa?U-a>icE1Tdd6fB12xGAmm(#F;*y}$ zG^>>S?P2hA^>bP0l+XkK Dk1=73 delta 419 zcmey*zL#TyIF|$m8v_HwgL2y+6BRWW(>8jkGftkxm@+wwQM10l*VoFwC^J1XFEPg@ zKe;qFHLt|e#a5{zw?Ho?GsVil%)-FX(A>np+z7}tG_*7{uynI@bu%z`u`o4paZ*wM zssx&WO|PkwrHP@lxtp1zv5BFftC5A7fw{AZnVFM`xudJ4nIll|WL+jn1*ke#TP70QpoVgWIbjlj#dBCcz{8bJGp{cCbfZ8$KcrgAI1r@Di?Ax z8zvbv=(um>cW7(oX-Uix3rb;Byv~;+^METk#?iG*Wzopr0E6myFaQ7m diff --git a/src/main/webapp/images/heading_4.png b/src/main/webapp/images/heading_4.png index cc7c93e016d8681154d44b1ab20d954b13a73522..70402535e034cb5de0a84a1bdaa63f6f7a226147 100644 GIT binary patch delta 332 zcmdnZ@t1vqIF}p;8v_G_nclsp6BRWWl{R{*Gfuw4s5Ci?F?;eZCf&)^OwtM_t|pGo z1{M|;#-;{_hOS1I=B@@#mXEa?U-a>iY##|dd6fB12xGEmm(#F;*y}$ zG^>>SA39Li+3d8i-#n!+x) z>1a#M8K8jkGftkxm@+wwQM10l*VoFwC^J1XFEPg@ zKe;qFHLt|e#a5{zw?Ho?GsVil%)-FX(A>np+z7}tG_*7{uynI@bu%z`u`o4paZ*wM zssx&WO|ONav$LV8g@Ku)v5BFftC5A7fw{AZnVFM`xudJ4nIll|WL+jn1&BIxH(cr_ z|6(+pyqHNphOlFbOM+6G(-C?npOLokAqu{h{#)SSz4?~&R?>T;U pJd^A#++ruOHQ@>qTLS|#1N#@9{S6Pkr~}Ps@O1TaS?83{1OS39eo_Dc diff --git a/src/main/webapp/images/heading_5.png b/src/main/webapp/images/heading_5.png index 1d6430daef557e27d1f5340fb2b0d35fd22f662e..ea482f8a2b83748bb6faadc752d2032fe3d36f6f 100644 GIT binary patch delta 329 zcmdnN@r!+eIF}p;8v_G_nclsp6BRWWl{R{*Gfuw4s5Ci?F?;eZCf&)^OwtOL#)dAg zuEvHI#-;{_hOS1I=B@@#mXEa?U-a>ii~h7dd6fBW8!M!=xku&h)a=@ zLUBn@YMNC_esXDUYF>$_i>*>cZh>A(W{MTm6$ZHUPA+10;+WERXa>+fd6V}r%cSW_ zY)!brq{P78^U?et&y2LVj6)7R5=IWwj%PBiWSGCuS((qlu~l~m2b-Xx?~9L&hg6O- zF65BC^|L`ne&d8$CKq)Tr^HCQM~f~N>xnwRAdtXdBd*?Gf4aO1Xa$3(tDnm{r-UW| D8mnN& delta 414 zcmeyxzJp_eIF|$m8v_HwgL2y+6BRWW(>8jkGftkxm@+wwQM10l*VoFwC^J1XFEPg@ zKe;qFHLt|e#a5{zw?Ho?GsVil%)-FX(A>np+z7}tG_*7{uynI@bu%z`u`o4paZ*wM zssx&WO|ONav$LV8g^8J?v5BFftC5A7fw{AZnVFM`xudJ4nIll|WL+jn1*ke>TP70QpoVgWIbjl4%-Q4*MLElF}Z?SCZT~<$KcrgAI1r@Di?Ax z8z!A#h?HB-x`e5wjjz{&fmL+d10@NU7L$d?**PYQu(v3cWISgssyX76b;)IWOF&Vo k%vydoU5Tv?j0y)B)_STpSBw8?1RBoZ>FVdQ&MBb@00WwMp8x;= diff --git a/src/main/webapp/images/title.png b/src/main/webapp/images/title.png index 707090a50c2957d962308ff46e5751ce24f46e76..5434e2be97f9517e2b16612288cf68d62a9816ad 100644 GIT binary patch delta 338 zcmdnYv4dlRIF}p;8v_G_nclsp8x{XC${Si37#fLwm{}MaT3VVoyP6rgnH!io zni?4zPqt%{QE)LZaWQZ)v9K^UaW*t`HL^5!HE^=Dba8aHaJDcobDmsU zXacq=DHN9krKVY>Lwm{}MaS{fQyx>>rq8JN3R zn3}jaO}1l_QLr#{b~ZG%urPBpHZe4GHL@@>Fn2aFGjlRAcXYKhbDUg-P-Ko%(Ke>U zXacq=DHN9krKVY>E|ZkESbD1cs#8pngqVW%p`{ZiIEL^lrN|3&S#461ylJjrW_Q2$ vS+imeqfQd%Ql(=Te