001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.web.client.contents;
017
018import com.google.gwt.user.client.rpc.AsyncCallback;
019import com.smartgwt.client.types.Alignment;
020import com.smartgwt.client.types.VerticalAlignment;
021import com.smartgwt.client.util.BooleanCallback;
022import com.smartgwt.client.util.SC;
023import com.smartgwt.client.widgets.Label;
024import com.smartgwt.client.widgets.events.ClickEvent;
025import com.smartgwt.client.widgets.events.ClickHandler;
026import com.smartgwt.client.widgets.layout.HLayout;
027import java.util.Collection;
028import org.modeshape.web.client.contents.ChildrenEditor.NodeRecord;
029import org.modeshape.web.client.grid.Grid;
030import org.modeshape.web.client.grid.Pager;
031import org.modeshape.web.shared.Align;
032import org.modeshape.web.shared.Columns;
033import org.modeshape.web.shared.JcrNode;
034
035/**
036 *
037 * @author kulikov
038 */
039public class ChildrenEditor extends Grid<NodeRecord, JcrNode> {
040
041    private JcrNode node;    
042    private final Contents contents;
043    private final RenameNodeDialog renameNodeDialog;
044    private final ChildNodesPager pager = new ChildNodesPager();
045    
046     
047    private Label hint;
048    
049    public ChildrenEditor(Contents contents) {
050        super("Child nodes");
051        this.contents = contents;
052        this.setFooterContent(pager);
053        renameNodeDialog = new RenameNodeDialog(contents);
054    }
055
056    public void show(JcrNode node) {
057        this.node = node;
058        
059        pager.setRecordsAmount((int)node.getChildCount());
060        pager.fetch(0);
061        
062        String hintText = node.hasBinaryContent() ? 
063                "This node has binary content attached. See bellow" :
064                "This node has no binary content attached";
065        hint.setContents(hintText);
066    }
067
068    @Override
069    protected HLayout tableHeader() {
070        HLayout header = new HLayout();
071        header.setHeight(30);
072        header.setBackgroundColor("#e6f1f6");
073
074        Label name = new Label("<b>Name</b>");
075        name.setWidth(150);
076        name.setIcon("icons/view_tree_modernist.png");
077
078        Label type = new Label("<b>Primary Type</b>");
079        type.setWidth(150);
080        type.setIcon("icons/documents.png");
081
082        Label path = new Label("<b>Path</b>");
083        path.setWidth100();
084        path.setIcon("icons/view_table.png");
085
086
087        header.addMember(name);
088        header.addMember(type);
089        header.addMember(path);
090
091        return header;
092    }
093
094    @SuppressWarnings("synthetic-access")
095    @Override
096    protected HLayout toolBar() {        
097        hint = new Label();
098        hint.setWidth100();
099        
100        Label hint2 = new Label();
101        hint2.setContents("Enable/Disbale properties");
102        hint2.setWidth(250);
103        hint2.setAlign(Alignment.RIGHT);
104        
105        Label detailsButton = new Label();
106        detailsButton.setTooltip("Show details");
107        detailsButton.setStyleName("button-label");
108        detailsButton.setWidth(16);
109        detailsButton.setIcon("icons/view_table.png");
110        detailsButton.addClickHandler(new ClickHandler() {
111            @Override
112            public void onClick(ClickEvent event) {
113                contents.toggleDetails();
114            }
115        });
116        
117        Columns col = new Columns(Align.LEFT, Align.CENTER);        
118        col.setBackgroundColor("#ffffff");
119        
120        col.setHeight(30);        
121        col.addMember(hint);
122        col.addMember(hint2);
123        col.addMember(detailsButton);
124        
125        return col;
126    }
127
128    @Override
129    protected NodeRecord[] records() {
130        NodeRecord[] recs = new NodeRecord[100];
131        for (int i = 0; i < recs.length; i++) {
132            recs[i] = new NodeRecord();
133        }
134        return recs;
135    }
136
137    @SuppressWarnings("synthetic-access")
138    @Override
139    protected void updateRecord(int pos, NodeRecord record, JcrNode value) {
140        if (pos <= 0) {            
141            record.setNodeAsParent(ChildrenEditor.this.node);
142            record.setVisible(!node.getPath().equals("/"));
143        } else {
144            record.setNode(value);
145        }        
146    }
147
148    public class NodeRecord extends HLayout {
149
150        private Label name = new Label();
151        private Label path = new Label();
152        private Label primaryType = new Label();
153        private Buttons buttons = new Buttons();
154        private JcrNode node;
155
156        public NodeRecord() {
157            super();
158            setStyleName("grid");
159            setHeight(30);
160
161            setDefaultLayoutAlign(VerticalAlignment.CENTER);
162            setDefaultLayoutAlign(Alignment.LEFT);
163
164            setLayoutAlign(VerticalAlignment.CENTER);
165            setLayoutAlign(Alignment.CENTER);
166
167            setAlign(VerticalAlignment.CENTER);
168            setAlign(Alignment.LEFT);
169
170            name.setStyleName("node-name");
171            name.setIcon("icons/folder.png");
172            name.addClickHandler(new ClickHandler() {
173                @SuppressWarnings("synthetic-access")
174                @Override
175                public void onClick(ClickEvent event) {
176                    contents.getAndDisplayNode(path(), true);
177                }
178            });
179
180            name.setWidth(150);
181            primaryType.setWidth(150);
182            primaryType.setStyleName("text");
183
184            path.setWidth100();
185            path.setStyleName("text");
186
187
188            addMember(name);
189            addMember(primaryType);
190            addMember(path);
191            addMember(buttons);
192        }
193
194        private String path() {
195            return node == null ? "/" : path.getContents();
196        }
197
198        private void setNode(JcrNode node) {
199            this.node = node;
200            this.name.setContents(node.getName());
201            this.path.setContents(node.getPath());
202            this.path.setVisible(true);
203            this.buttons.setVisible(true);
204            this.buttons.setNode(node);
205            this.primaryType.setContents(node.getPrimaryType());
206        }
207
208        private void setNodeAsParent(JcrNode node) {
209            this.node = node;
210            this.name.setContents("<b>../</b>");
211            this.path.setContents(parent(node.getPath()));
212            this.path.setVisible(false);
213            this.buttons.setVisible(false);
214            this.buttons.setNode(node);
215            this.primaryType.setContents("");
216        }
217
218        private String parent(String path) {
219            if (path == null) {
220                return "/";
221            }
222
223            path = path.substring(0, path.lastIndexOf('/'));
224            if (path.length() == 0) {
225                return "/";
226            }
227
228            return path;
229        }
230    }
231
232    private class Buttons extends HLayout {
233
234        private Label editButton = new Label();
235        private Label remButton = new Label();
236        private JcrNode node;
237        
238        public Buttons() {
239            this.setWidth(36);
240
241            this.setDefaultLayoutAlign(Alignment.RIGHT);
242            this.setLayoutAlign(Alignment.RIGHT);
243            this.setAlign(Alignment.RIGHT);
244            this.setDefaultLayoutAlign(VerticalAlignment.CENTER);
245            this.setLayoutAlign(VerticalAlignment.CENTER);
246            this.setAlign(VerticalAlignment.CENTER);
247
248            editButton.setWidth(16);
249            editButton.setHeight(16);
250            editButton.setIcon("icons/pencil.png");
251            editButton.setStyleName("button-label");
252            editButton.addClickHandler(new ClickHandler() {
253                @Override
254                public void onClick(ClickEvent event) {
255                    renameNodeDialog.showModal(node);
256                }
257            });
258
259            remButton.setWidth(16);
260            remButton.setHeight(16);
261            remButton.setIcon("icons/cross.png");
262            remButton.setStyleName("button-label");
263            remButton.addClickHandler(new ClickHandler() {
264                @Override
265                public void onClick(ClickEvent event) {
266                    SC.ask("Remove node", "Do you want to remove node?", new BooleanCallback() {
267                        @Override
268                        public void execute(Boolean confirmed) {
269                            if (confirmed) {
270                                contents.removeNode(node);
271                            }
272                        }
273                    });
274                }
275            });
276
277            addMember(editButton);
278            addMember(remButton);
279        }
280        
281        protected void setNode(JcrNode node) {
282            this.node = node;
283        }
284    }
285    
286    private class ChildNodesPager extends Pager {
287
288        @Override
289        public void fetch(int index) {
290            contents.jcrService().childNodes(contents.repository(), 
291                    contents.workspace(), contents.path(), 
292                    index  * pager.getRecordsPerPage(), 
293                    pager.getRecordsPerPage(), new AsyncCallback<Collection<JcrNode>>() {
294                @Override
295                public void onFailure(Throwable caught) {
296                    SC.say(caught.getMessage());
297                }
298
299                @Override
300                public void onSuccess(Collection<JcrNode> nodes) {
301                    setValues(nodes);
302                }
303            });
304        }
305        
306    }
307}