001    /**
002     * Copyright 2010 The Kuali Foundation Licensed under the
003     * Educational Community License, Version 2.0 (the "License"); you may
004     * not use this file except in compliance with the License. You may
005     * obtain a copy of the License at
006     *
007     * http://www.osedu.org/licenses/ECL-2.0
008     *
009     * Unless required by applicable law or agreed to in writing,
010     * software distributed under the License is distributed on an "AS IS"
011     * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
012     * or implied. See the License for the specific language governing
013     * permissions and limitations under the License.
014     */
015    
016    package org.kuali.student.lum.common.client.lo;
017    
018    import java.util.ArrayList;
019    import java.util.HashMap;
020    import java.util.Map;
021    
022    import org.kuali.student.common.assembly.data.QueryPath;
023    import org.kuali.student.common.ui.client.configurable.mvc.FieldDescriptor;
024    import org.kuali.student.common.ui.client.configurable.mvc.sections.VerticalSection;
025    import org.kuali.student.common.ui.client.theme.Theme;
026    import org.kuali.student.common.ui.client.widgets.field.layout.element.MessageKeyInfo;
027    
028    import com.google.gwt.event.dom.client.MouseMoveHandler;
029    import com.google.gwt.event.logical.shared.ValueChangeEvent;
030    import com.google.gwt.event.logical.shared.ValueChangeHandler;
031    import com.google.gwt.event.shared.HandlerRegistration;
032    import com.google.gwt.user.client.DOM;
033    import com.google.gwt.user.client.Event;
034    import com.google.gwt.user.client.ui.HasValue;
035    import com.google.gwt.user.client.ui.HorizontalPanel;
036    import com.google.gwt.user.client.ui.Image;
037    import com.google.gwt.user.client.ui.Label;
038    import com.google.gwt.user.client.ui.VerticalPanel;
039    import com.google.gwt.user.client.ui.Widget;
040    
041    
042    public class OutlineManager extends VerticalSection implements HasValue<OutlineNodeModel> {
043        OutlineNodeModel<?> outlineModel;
044        String startOfPath;
045        String endOfPath;
046        String middleOfPath;
047    
048        public OutlineManager(String pathStart, String pathMiddle, String pathEnd) {
049            startOfPath = pathStart;
050            middleOfPath = pathMiddle;
051            endOfPath = pathEnd;
052            }
053    
054            public void render() {
055            Map<Integer, Integer> levelIndexes = new HashMap<Integer, Integer>();
056            int currIndent = 0;
057    
058            levelIndexes.put(0, -1); // first node increments the 0'th indent's index
059            OutlineNode[] outlineNodes = outlineModel.toOutlineNodes();
060            for (final OutlineNode aNode : outlineNodes) {
061                            NodePanel nodePanel = new NodePanel();
062                            nodePanel.setStyleName("KS-LONodePanel");
063                            nodePanel.setOutlineNode(aNode);
064                if (aNode.getIndentLevel() > currIndent) {
065                    currIndent = aNode.getIndentLevel();
066                    levelIndexes.put(currIndent, 0);
067                } else if (aNode.getIndentLevel() < currIndent) {
068                    currIndent = aNode.getIndentLevel();
069                    levelIndexes.put(currIndent, levelIndexes.get(currIndent) + 1);
070                } else {
071                    levelIndexes.put(currIndent, levelIndexes.get(currIndent) + 1);
072                }
073    
074                addField(getFieldKey(currIndent, levelIndexes), null, nodePanel, null);
075    
076                            showAllToolbar();
077                    }
078            }
079    
080        private String getFieldKey(int currIndent, Map<Integer, Integer> levelIndexes) {
081            StringBuilder keyBuilder = new StringBuilder(startOfPath);
082    
083            keyBuilder.append("/").append(levelIndexes.get(0)).append("/");
084            for (int idx = 1; idx <= currIndent; idx++) {
085                keyBuilder.append(middleOfPath).append("/").append(levelIndexes.get(idx)).append("/");
086            }
087            keyBuilder.append(endOfPath);
088    
089            return keyBuilder.toString();
090        }
091    
092        private FieldDescriptor addField(String fieldKey, MessageKeyInfo messageKey, Widget widget, String parentPath) {
093            QueryPath path = QueryPath.concat(parentPath, fieldKey);
094    
095            FieldDescriptor fd = new FieldDescriptor(path.toString(), messageKey, null);
096            if (widget != null) {
097                fd.setFieldWidget(widget);
098                fd.setHasHadFocus(true);
099            }
100            this.addField(fd);
101            return fd;
102        }
103    
104            public void closeAllToolbar(){
105            for (FieldDescriptor fd : this.getFields()) {
106                if (fd.getFieldWidget() instanceof NodePanel) {
107                    ((NodePanel) fd.getFieldWidget()).hideToolbar();
108                }
109            }
110            }
111            
112            public void showAllToolbar(){
113            for (FieldDescriptor fd : this.getFields()) {
114                if (fd.getFieldWidget() instanceof NodePanel) {
115                    ((NodePanel) fd.getFieldWidget()).showToolbar();
116                }
117            }
118            }
119            
120            class NodePanel extends  VerticalPanel{
121                    OutlineManagerToolbar toolbar = new OutlineManagerToolbar();
122                    HorizontalPanel emptySpacePanel = new HorizontalPanel();
123                    ArrayList<MouseMoveHandler> mouseMoveHandlerList = new ArrayList<MouseMoveHandler>();
124                    HorizontalPanel horitonalPanel = new HorizontalPanel();
125            OutlineNode currentNode;
126                    NodePanel() {
127                            toolbar.setModel(outlineModel);
128                            horitonalPanel.setStyleName("KS-LOHNodePanel");
129                            super.sinkEvents(Event.ONMOUSEMOVE);
130                            super.sinkEvents(Event.ONMOUSEOUT);
131                            emptySpacePanel.setStyleName("KS-LOOutlineManagerToolbar");
132                            Image ieHack = Theme.INSTANCE.getCommonImages().getSpacer();
133                            emptySpacePanel.add(ieHack);
134                            super.insert(emptySpacePanel,0);
135                    }
136    
137            public void setOutlineNode(OutlineNode aNode) {
138                            currentNode = aNode;
139                            for (int i = 0; i < aNode.getIndentLevel(); i++) {
140                                    Label label = new Label();
141                                    label.setStyleName("KS-LONodeIndent");
142                                    horitonalPanel.add(label);
143    
144                                    // space for toolbar
145                                    label = new Label();
146                                    label.setStyleName("KS-LONodeIndentToolbar");
147                                    toolbar.insert(label, 0);
148                            }
149                            Widget userWidget = (Widget) aNode.getUserObject();
150                            userWidget.setStyleName("KS-LOaNode");
151                            horitonalPanel.add(userWidget);
152    
153                            add(horitonalPanel);
154                    }
155    
156                    public void addMouseMoveHandler(MouseMoveHandler handler) {
157                            mouseMoveHandlerList.add(handler);
158                    }
159    
160                    public void setToolbar(OutlineManagerToolbar t) {
161                            toolbar = t;
162                    }
163                    public void showToolbar(){
164                            super.remove(emptySpacePanel);
165                            super.insert(toolbar, 0);
166                    }
167                    public void hideToolbar(){
168                            super.remove(toolbar);
169                            super.insert(emptySpacePanel,0);
170                    }
171                    @Override
172            public void onBrowserEvent(Event event) {
173                            switch (DOM.eventGetType(event)) {
174                            case Event.ONMOUSEMOVE: {
175                        outlineModel.setCurrentNode(currentNode);
176                                    break;
177                            }
178                            case Event.ONMOUSEOUT:
179                                    break;
180                            }
181                            super.onBrowserEvent(event);
182                    }
183    
184            @Override
185            protected void onEnsureDebugId(String baseID) {
186                super.onEnsureDebugId(baseID);
187                toolbar.ensureDebugId(baseID);
188                if (currentNode != null) {
189                    Object userObject = currentNode.getUserObject();
190                    if (userObject instanceof Widget) {
191                        ((Widget) userObject).ensureDebugId(baseID);
192                    }
193                }
194            }
195                    
196                    
197            }
198            
199            @Override
200        public OutlineNodeModel getValue() {
201                    return outlineModel;
202            }
203    
204            @Override
205        public void setValue(OutlineNodeModel value) {
206                    outlineModel = value;           
207            }
208    
209            @Override
210        public void setValue(OutlineNodeModel value, boolean fireEvents) {
211                    setValue(value);
212            }
213    
214            @Override
215        public HandlerRegistration addValueChangeHandler(ValueChangeHandler<OutlineNodeModel> handler) {
216                    return addHandler(handler, ValueChangeEvent.getType());
217            }
218    }