Project

General

Profile

1
/*
2
 * Copyright 2006 Google Inc.
3
 * 
4
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5
 * use this file except in compliance with the License. You may obtain a copy of
6
 * the License at
7
 * 
8
 * http://www.apache.org/licenses/LICENSE-2.0
9
 * 
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
 * License for the specific language governing permissions and limitations under
14
 * the License.
15
 */
16
package org.kepler.web.client;
17

    
18
import org.kepler.web.client.DynaTableDataProvider.RowDataAcceptor;
19

    
20
import com.google.gwt.user.client.ui.Button;
21
import com.google.gwt.user.client.ui.ClickListener;
22
import com.google.gwt.user.client.ui.Composite;
23
import com.google.gwt.user.client.ui.DockPanel;
24
import com.google.gwt.user.client.ui.Grid;
25
import com.google.gwt.user.client.ui.HasAlignment;
26
import com.google.gwt.user.client.ui.HorizontalPanel;
27
import com.google.gwt.user.client.ui.HTML;
28
import com.google.gwt.user.client.ui.Widget;
29
import com.google.gwt.user.client.ui.TextBox;
30
import com.google.gwt.user.client.ui.TableListener;
31
import com.google.gwt.user.client.ui.SourcesTableEvents;
32
import com.google.gwt.user.client.ui.Image;
33
import com.google.gwt.user.client.ui.DialogBox;
34
import com.google.gwt.user.client.ui.Frame;
35

    
36
public class DynaTableWidget extends Composite implements TableListener{
37

    
38
  private class NavBar extends Composite implements ClickListener {
39

    
40
    public NavBar() {
41
      initWidget(bar);
42
      bar.setStyleName("navbar");
43
      status.setStyleName("status");
44
      
45
      HorizontalPanel searchPanel = new HorizontalPanel();
46
      searchField.setVisibleLength(12);
47
      searchButton.setStyleName("searchButton");
48
      searchPanel.add(searchField);
49
      searchPanel.add(searchButton);
50
      
51
      HorizontalPanel buttons = new HorizontalPanel();
52
      buttons.add(gotoFirst);
53
      buttons.add(gotoPrev);
54
      buttons.add(gotoNext);
55
      buttons.add(gotoLast);
56
      bar.add(buttons, DockPanel.EAST);
57
      bar.setCellHorizontalAlignment(buttons, DockPanel.ALIGN_RIGHT);
58
      
59
      HorizontalPanel statusPanel = new HorizontalPanel();
60
      statusPanel.add(statusImage);
61
      statusPanel.add(new HTML("  "));
62
      statusPanel.add(status);
63
      bar.add(statusPanel, DockPanel.CENTER);
64
      
65
      bar.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
66
      bar.setCellHorizontalAlignment(statusPanel, HasAlignment.ALIGN_RIGHT);
67
      bar.setCellVerticalAlignment(statusPanel, HasAlignment.ALIGN_MIDDLE);
68
      bar.setCellWidth(statusPanel, "100%");
69
      
70
      bar.add(searchPanel, DockPanel.WEST);
71
      
72

    
73
      // Initialize prev & first button to disabled.
74
      //
75
      gotoPrev.setEnabled(false);
76
      gotoFirst.setEnabled(false);
77
    }
78

    
79
    public void onClick(Widget sender) {
80
      if (sender == gotoNext) {
81
        startRow += getDataRowCount();
82
        selectRow(-1);
83
        refresh();
84
      } else if (sender == gotoPrev) {
85
        startRow -= getDataRowCount();
86
        if (startRow < 0) {
87
          startRow = 0;
88
        }
89
        selectRow(-1);
90
        refresh();
91
      } else if (sender == gotoFirst) {
92
        startRow = 0;
93
        selectRow(-1);
94
        refresh();
95
      } else if (sender == gotoLast) {
96
        startRow = getMaxRowCount() - (getMaxRowCount() % getRowInc());
97
        selectRow(-1);
98
        refresh();
99
      } else if(sender == searchButton) {
100
        searchString = searchField.getText();
101
        startRow = 0;
102
        selectRow(-1);
103
        search(searchField.getText());
104
      }
105
    }
106

    
107
    public final DockPanel bar = new DockPanel();
108
    public final Button gotoFirst = new Button("&lt;&lt;", this);
109
    public final Button gotoNext = new Button("&gt;", this);
110
    public final Button gotoPrev = new Button("&lt;", this);
111
    public final Button gotoLast = new Button("&gt;&gt;", this);
112
    public final Button searchButton = new Button("Search", this);
113
    public final TextBox searchField = new TextBox();
114
    public final HTML status = new HTML();
115
    public final Image statusImage = new Image("spinner-anim.gif");
116
  }
117

    
118
  private class RowDataAcceptorImpl implements RowDataAcceptor {
119
    
120
    public void accept(int startRow, String[][] data) {
121
      int destRowCount = getDataRowCount();
122
      int destColCount = grid.getCellCount(0);
123
      assert (data.length <= destRowCount) : "Too many rows";
124

    
125
      int srcRowIndex = 0;
126
      int srcRowCount = data.length;
127
      int destRowIndex = 1; // skip navbar row
128
      for (; srcRowIndex < srcRowCount; ++srcRowIndex, ++destRowIndex) {
129
        String[] srcRowData = data[srcRowIndex];
130
        assert (srcRowData.length == destColCount) : " Column count mismatch";
131
        for (int srcColIndex = 0; srcColIndex < destColCount; ++srcColIndex) {
132
          String cellHTML = srcRowData[srcColIndex];
133
          grid.setText(destRowIndex, srcColIndex, cellHTML);
134
          grid.getCellFormatter().setStyleName(destRowIndex, 0, "infoIcon");
135
        }
136
      }
137

    
138
      // Clear remaining table rows.
139
      //
140
      boolean isLastPage = false;
141
      for (; destRowIndex < destRowCount + 1; ++destRowIndex) {
142
        isLastPage = true;
143
        for (int destColIndex = 0; destColIndex < destColCount; ++destColIndex) {
144
          grid.clearCell(destRowIndex, destColIndex);
145
        }
146
      }
147

    
148
      // Synchronize the nav buttons.
149
      //
150
      navbar.gotoNext.setEnabled(!isLastPage);
151
      navbar.gotoFirst.setEnabled(startRow > 0);
152
      navbar.gotoPrev.setEnabled(startRow > 0);
153
      navbar.gotoLast.setEnabled(!isLastPage);
154

    
155
      // Update the status message.
156
      //
157
      setStatusText((startRow + 1) + " - " + (startRow + srcRowCount) + " of " + 
158
        getMaxRowCount());
159
      setStatusImage(false);
160
      currentEndRecordNum = startRow + srcRowCount;
161
      currentBeginRecordNum = startRow + 1;
162
    }
163

    
164
    public void failed(Throwable caught) {
165
      String msg = "Failed to access data";
166
      if (caught != null) {
167
        msg += ": " + caught.getMessage();
168
      }
169
      setStatusText(msg);
170
    }
171
  }
172
  
173
  private static class InfoDialog extends DialogBox implements ClickListener {
174
    
175
    public InfoDialog(String title, String docid) {
176
      
177
      setText(title);
178

    
179
      Frame iframe = new Frame("http://library.kepler-project.org/kepler/metacat?action=read&docid=" + docid + "&qformat=kepler");
180
      Button closeButton = new Button("Close", this);
181
      /*HTML msg = new HTML(
182
        "<center>This is an example of a standard dialog box component.<br>  "
183
          + "You can put pretty much anything you like into it,<br>such as the "
184
          + "following IFRAME:</center>", true);*/
185

    
186
      DockPanel dock = new DockPanel();
187
      dock.setSpacing(4);
188

    
189
      dock.add(closeButton, DockPanel.SOUTH);
190
      //dock.add(msg, DockPanel.NORTH);
191
      dock.add(iframe, DockPanel.CENTER);
192

    
193
      dock.setCellHorizontalAlignment(closeButton, DockPanel.ALIGN_RIGHT);
194
      dock.setCellWidth(iframe, "100%");
195
      dock.setWidth("100%");
196
      iframe.setWidth("80em");
197
      iframe.setHeight("50em");
198
      setWidget(dock);
199
    }
200

    
201
    public void onClick(Widget sender) {
202
      hide();
203
    }
204
  }
205

    
206
  public DynaTableWidget(DynaTableDataProvider provider, String[] columns,
207
      String[] columnStyles, int rowCount) {
208
    rowInc = rowCount;
209
    if (columns.length == 0) {
210
      throw new IllegalArgumentException(
211
        "expecting a positive number of columns");
212
    }
213

    
214
    if (columnStyles != null && columns.length != columnStyles.length) {
215
      throw new IllegalArgumentException("expecting as many styles as columns");
216
    }
217

    
218
    this.provider = provider;
219
    initWidget(outer);
220
    grid.setStyleName("table");
221
    grid.addTableListener(this);
222
    outer.add(navbar, DockPanel.NORTH);
223
    outer.add(grid, DockPanel.CENTER);
224
    initTable(columns, columnStyles, rowCount);
225
    setStyleName("DynaTable-DynaTableWidget");
226
  }
227

    
228
  private void initTable(String[] columns, String[] columnStyles, int rowCount) {
229
    // Set up the header row.  It's one greater than the number of visible rows.
230
    //
231

    
232
    grid.resize(rowCount+1, columns.length);
233
    for (int i = 0, n = columns.length; i < n; i++) {
234
      grid.setText(0, i, columns[i]);
235
      if (columnStyles != null) {
236
        grid.getCellFormatter().setStyleName(0, i, columnStyles[i] + " header");
237
      }
238
    }
239
  }
240

    
241
  public void setStatusText(String text) {
242
    navbar.status.setText(text);
243
  }
244

    
245
  public void clearStatusText() {
246
    navbar.status.setHTML("&nbsp;");
247
  }
248
  
249
  public void setStatusImage(boolean on)
250
  {
251
    //if on turn the image on
252
    navbar.statusImage.setVisible(on);
253
  }
254

    
255
  public void refresh() {
256
    // Disable buttons temporarily to stop the user from running off the end.
257
    //
258
    search(searchString);
259
  }
260
  
261
  public void search(String searchTerm) {
262
    navbar.gotoFirst.setEnabled(false);
263
    navbar.gotoPrev.setEnabled(false);
264
    navbar.gotoNext.setEnabled(false);
265
    navbar.gotoLast.setEnabled(false);
266

    
267
    setStatusText("Searching...");
268
    setStatusImage(true);
269
    provider.updateRowData(startRow, grid.getRowCount() - 1, acceptor, searchTerm);
270
    
271
    for(int i=0; i<grid.getRowCount(); i++)
272
    {
273
      if(grid.getText(i, 1) == null || 
274
         grid.getText(i, 1).trim().equals("") || 
275
         grid.getHTML(i,1).equals("&nbsp;"))
276
      { //remove the info icon style if there is nothing in the row
277
        grid.getCellFormatter().removeStyleName(i, 0, "infoIcon");
278
      }
279
    }
280
  }
281

    
282
  public void setRowCount(int rows) {
283
    grid.resizeRows(rows);
284
  }
285
  
286
  public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
287
    // Select the row that was clicked (-1 to account for header row).
288
    if(((row + currentBeginRecordNum) - 2) < currentEndRecordNum)
289
    {
290
      if (row > 0)
291
      {
292
        selectRow(row - 1);
293
      }
294
      
295
      if(cell == 0)
296
      {
297
        //create the dialog and send the name and docid to the dialog
298
        DialogBox dlg = new InfoDialog(grid.getText(row,1), grid.getText(row,2));
299
        int left = 50;
300
        int top = 50;
301
        dlg.setPopupPosition(left, top);
302
        dlg.show();
303
      }
304
    }
305
  }
306
  
307
  /**
308
   * Selects the given row (relative to the current page).
309
   * 
310
   * @param row the row to be selected
311
   */
312
  private void selectRow(int row) {
313

    
314
    styleRow(selectedRow, false);
315
    styleRow(row, true);
316

    
317
    selectedRow = row;
318
  }
319

    
320
  private void styleRow(int row, boolean selected) {
321
    if (row != -1) {
322
      if (selected)
323
      {
324
        //grid.getRowFormatter().addStyleName(row + 1, "SelectedRow");
325
        //don't select the info icon
326
        grid.getCellFormatter().setStyleName(row + 1, 1, "SelectedRow");
327
        grid.getCellFormatter().setStyleName(row + 1, 2, "SelectedRow");
328
      }
329
      else
330
      {
331
        //grid.getRowFormatter().removeStyleName(row + 1, "SelectedRow");
332
        grid.getCellFormatter().removeStyleName(row + 1, 1, "SelectedRow");
333
        grid.getCellFormatter().removeStyleName(row + 1, 2, "SelectedRow");
334
      }
335
    }
336
  }
337
  
338
  private int getDataRowCount() {
339
    return grid.getRowCount() - 1;
340
  }
341
  
342
  public int getMaxRowCount() {
343
    return maxRowCount;
344
  }
345
  
346
  public void setMaxRowCount(int max) {
347
    maxRowCount = max;
348
  }
349
  
350
  private int getRowInc() {
351
    return rowInc;
352
  }
353

    
354
  private final RowDataAcceptor acceptor = new RowDataAcceptorImpl();
355
  private final NavBar navbar = new NavBar();
356
  private final DockPanel outer = new DockPanel();
357
  private final DynaTableDataProvider provider;
358
  private int startRow = 0;
359
  private Grid grid = new Grid();
360
  private int maxRowCount = 0;
361
  private int rowInc;
362
  private int currentEndRecordNum = -1;
363
  private int currentBeginRecordNum = -1;
364
  private String searchString = null;
365
  private int startIndex, selectedRow = -1;
366
}
(2-2/7)