123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259 |
- /* *************************************************************************
-
- IT Mill Toolkit
-
- Development of Browser User Interfaces Made Easy
-
- Copyright (C) 2000-2006 IT Mill Ltd
-
- *************************************************************************
-
- This product is distributed under commercial license that can be found
- from the product package on license.pdf. Use of this product might
- require purchasing a commercial license from IT Mill Ltd. For guidelines
- on usage, see licensing-guidelines.html
-
- *************************************************************************
-
- For more information, contact:
-
- IT Mill Ltd phone: +358 2 4802 7180
- Ruukinkatu 2-4 fax: +358 2 4802 7181
- 20540, Turku email: info@itmill.com
- Finland company www: www.itmill.com
-
- Primary source for information and releases: www.itmill.com
-
- ********************************************************************** */
-
- package com.itmill.toolkit.ui;
-
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.LinkedHashSet;
- import java.util.LinkedList;
- import java.util.Map;
- import java.util.Set;
- import java.util.StringTokenizer;
-
- import com.itmill.toolkit.data.Container;
- import com.itmill.toolkit.data.Item;
- import com.itmill.toolkit.data.Property;
- import com.itmill.toolkit.data.util.ContainerOrderedWrapper;
- import com.itmill.toolkit.data.util.IndexedContainer;
- import com.itmill.toolkit.event.Action;
- import com.itmill.toolkit.terminal.KeyMapper;
- import com.itmill.toolkit.terminal.PaintException;
- import com.itmill.toolkit.terminal.PaintTarget;
- import com.itmill.toolkit.terminal.Resource;
- import com.itmill.toolkit.terminal.Sizeable;
-
- /**
- * Table component is used for representing data or components in pageable and
- * selectable table.
- *
- * @author IT Mill Ltd.
- * @version @VERSION@
- * @since 3.0
- */
- public class Table extends Select implements Action.Container,
- Container.Ordered, Container.Sortable, Sizeable {
-
- private static final int CELL_KEY = 0;
-
- private static final int CELL_HEADER = 1;
-
- private static final int CELL_ICON = 2;
-
- private static final int CELL_ITEMID = 3;
-
- private static final int CELL_FIRSTCOL = 4;
-
- /** Width of the table or -1 if unspecified */
- private int width = -1;
-
- /** Height of the table or -1 if unspecified */
- private int height = -1;
-
- /** Width unit */
- private int widthUnit = Sizeable.UNITS_PIXELS;
-
- /** Height unit */
- private int heightUnit = Sizeable.UNITS_PIXELS;
-
- /**
- * Left column alignment. <b>This is the default behaviour. </b>
- */
- public static final String ALIGN_LEFT = "b";
-
- /** Center column alignment. */
- public static final String ALIGN_CENTER = "c";
-
- /** Right column alignment. */
- public static final String ALIGN_RIGHT = "e";
-
- /**
- * Column header mode: Column headers are hidden. <b>This is the default
- * behaviour. </b>
- */
- public static final int COLUMN_HEADER_MODE_HIDDEN = -1;
-
- /**
- * Column header mode: Property ID:s are used as column headers.
- */
- public static final int COLUMN_HEADER_MODE_ID = 0;
-
- /**
- * Column header mode: Column headers are explicitly specified with
- * <code>setColumnHeaders()</code>
- */
- public static final int COLUMN_HEADER_MODE_EXPLICIT = 1;
-
- /**
- * Column header mode: Column headers are explicitly specified with
- * <code>setColumnHeaders()</code>
- */
- public static final int COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = 2;
-
- /**
- * Row caption mode: The row headers are hidden. <b>This is the default
- * mode. </b>
- */
- public static final int ROW_HEADER_MODE_HIDDEN = -1;
-
- /**
- * Row caption mode: Items Id-objects toString() is used as row caption.
- */
- public static final int ROW_HEADER_MODE_ID = Select.ITEM_CAPTION_MODE_ID;
-
- /**
- * Row caption mode: Item-objects toString() is used as row caption.
- */
- public static final int ROW_HEADER_MODE_ITEM = Select.ITEM_CAPTION_MODE_ITEM;
-
- /**
- * Row caption mode: Index of the item is used as item caption. * The index
- * mode can only be used with the containers implementing Container.Indexed
- * interface.
- */
- public static final int ROW_HEADER_MODE_INDEX = Select.ITEM_CAPTION_MODE_INDEX;
-
- /**
- * Row caption mode: Item captions are explicitly specified.
- */
- public static final int ROW_HEADER_MODE_EXPLICIT = Select.ITEM_CAPTION_MODE_EXPLICIT;
-
- /**
- * Row caption mode: Item captions are read from property specified with
- * <code>setItemCaptionPropertyId</code>.
- */
- public static final int ROW_HEADER_MODE_PROPERTY = Select.ITEM_CAPTION_MODE_PROPERTY;
-
- /**
- * Row caption mode: Only icons are shown, the captions are hidden.
- */
- public static final int ROW_HEADER_MODE_ICON_ONLY = Select.ITEM_CAPTION_MODE_ICON_ONLY;
-
- /**
- * Row caption mode: Item captions are explicitly specified, but if the
- * caption is missing, the item id objects <code>toString()</code> is used
- * instead.
- */
- public static final int ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = Select.ITEM_CAPTION_MODE_EXPLICIT_DEFAULTS_ID;
-
- /* Private table extensions to Select *********************************** */
-
- /** True if column collapsing is allowed */
- private boolean columnCollapsingAllowed = false;
-
- /** True if reordering of columns is allowed on the client side */
- private boolean columnReorderingAllowed = false;
-
- /** Keymapper for column ids */
- private KeyMapper columnIdMap = new KeyMapper();
-
- /** Holds visible column propertyIds - in order */
- private LinkedList visibleColumns = new LinkedList();
-
- /** Holds propertyIds of currently collapsed columns */
- private HashSet collapsedColumns = new HashSet();
-
- /** Holds headers for visible columns (by propertyId) */
- private HashMap columnHeaders = new HashMap();
-
- /** Holds icons for visible columns (by propertyId) */
- private HashMap columnIcons = new HashMap();
-
- /** Holds alignments for visible columns (by propertyId) */
- private HashMap columnAlignments = new HashMap();
-
- /** Holds value of property pageLength. 0 disables paging. */
- private int pageLength = 0;
-
- /** Id the first item on the current page. */
- private Object currentPageFirstItemId = null;
-
- /** Index of the first item on the current page. */
- private int currentPageFirstItemIndex = 0;
-
- /** Holds value of property pageBuffering. */
- private boolean pageBuffering = false;
-
- /** Holds value of property selectable. */
- private boolean selectable = false;
-
- /** Holds value of property columnHeaderMode. */
- private int columnHeaderMode = COLUMN_HEADER_MODE_HIDDEN;
-
- /** True iff the row captions are hidden. */
- private boolean rowCaptionsAreHidden = true;
-
- /** Page contents buffer used in buffered mode */
- private Object[][] pageBuffer = null;
-
- /**
- * List of properties listened - the list is kept to release the listeners
- * later.
- */
- private LinkedList listenedProperties = null;
-
- /** List of visible components - the is used for needsRepaint calculation. */
- private LinkedList visibleComponents = null;
-
- /** List of action handlers */
- private LinkedList actionHandlers = null;
-
- /** Action mapper */
- private KeyMapper actionMapper = null;
-
- /** Table cell editor factory */
- private FieldFactory fieldFactory = new BaseFieldFactory();
-
- /** Is table editable */
- private boolean editable = false;
-
- /** Current sorting direction */
- private boolean sortAscending = true;
-
- /** Currently table is sorted on this propertyId */
- private Object sortContainerPropertyId = null;
-
- /** Is table sorting disabled alltogether; even if some of the properties would be
- * sortable. */
- private boolean sortDisabled = false;
-
- /** Number of rows explicitly requested by the client to be painted on next paint.
- * This is -1 if no request by the client is made. Painting the component will automatically
- * reset this to -1.
- */
- private int reqRowsToPaint = -1;
-
- /** Index of the first rows explicitly requested by the client to be painted.
- * This is -1 if no request by the client is made. Painting the component will automatically
- * reset this to -1.
- */
- private int reqFirstRowToPaint = -1;
-
- /* Table constructors *************************************************** */
-
- /** Create new empty table */
- public Table() {
- setRowHeaderMode(ROW_HEADER_MODE_HIDDEN);
- }
-
- /** Create new empty table with caption. */
- public Table(String caption) {
- this();
- setCaption(caption);
- }
-
- /** Create new table with caption and connect it to a Container. */
- public Table(String caption, Container dataSource) {
- this();
- setCaption(caption);
- setContainerDataSource(dataSource);
- }
-
- /* Table functionality ************************************************** */
-
- /**
- * Get the array of visible column property id:s.
- *
- * <p>
- * The columns are show in the order of their appearance in this array
- * </p>
- *
- * @return Value of property availableColumns.
- */
- public Object[] getVisibleColumns() {
- if (this.visibleColumns == null) {
- return null;
- }
- return this.visibleColumns.toArray();
- }
-
- /**
- * Set the array of visible column property id:s.
- *
- * <p>
- * The columns are show in the order of their appearance in this array
- * </p>
- *
- * @param availableColumns
- * Array of shown property id:s.
- */
- public void setVisibleColumns(Object[] visibleColumns) {
-
- // Visible columns must exist
- if (visibleColumns == null)
- throw new NullPointerException(
- "Can not set visible columns to null value");
-
- // Check that the new visible columns contains no nulls and properties
- // exist
- Collection properties = getContainerPropertyIds();
- for (int i = 0; i < visibleColumns.length; i++) {
- if (visibleColumns[i] == null)
- throw new NullPointerException("Properties must be non-nulls");
- else if (!properties.contains(visibleColumns[i]))
- throw new IllegalArgumentException(
- "Properties must exist in the Container, missing property: "
- + visibleColumns[i]);
- }
-
- // If this is called befor the constructor is finished, it might be
- // uninitialized
- LinkedList newVC = new LinkedList();
- for (int i = 0; i < visibleColumns.length; i++) {
- newVC.add(visibleColumns[i]);
- }
-
- // Remove alignments, icons and headers from hidden columns
- if (this.visibleColumns != null)
- for (Iterator i = this.visibleColumns.iterator(); i.hasNext();) {
- Object col = i.next();
- if (!newVC.contains(col)) {
- setColumnHeader(col, null);
- setColumnAlignment(col, null);
- setColumnIcon(col, null);
- }
- }
-
- this.visibleColumns = newVC;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Get the headers of the columns.
- *
- * <p>
- * The headers match the property id:s given my the set visible column
- * headers. The table must be set in either
- * <code>ROW_HEADER_MODE_EXPLICIT</code> or
- * <code>ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID</code> mode to show the
- * headers. In the defaults mode any nulls in the headers array are replaced
- * with id.toString() outputs when rendering.
- * </p>
- *
- * @return Array of column headers.
- */
- public String[] getColumnHeaders() {
- if (this.columnHeaders == null) {
- return null;
- }
- String[] headers = new String[this.visibleColumns.size()];
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) {
- headers[i] = (String) this.columnHeaders.get(it.next());
- }
- return headers;
- }
-
- /**
- * Set the headers of the columns.
- *
- * <p>
- * The headers match the property id:s given my the set visible column
- * headers. The table must be set in either
- * <code>ROW_HEADER_MODE_EXPLICIT</code> or
- * <code>ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID</code> mode to show the
- * headers. In the defaults mode any nulls in the headers array are replaced
- * with id.toString() outputs when rendering.
- * </p>
- *
- * @param columnHeaders
- * Array of column headers that match the
- * <code>getVisibleColumns()</code>.
- */
- public void setColumnHeaders(String[] columnHeaders) {
-
- if (columnHeaders.length != this.visibleColumns.size())
- throw new IllegalArgumentException(
- "The length of the headers array must match the number of visible columns");
-
- this.columnHeaders.clear();
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext()
- && i < columnHeaders.length; i++) {
- this.columnHeaders.put(it.next(), columnHeaders[i]);
- }
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Get the icons of the columns.
- *
- * <p>
- * The icons in headers match the property id:s given my the set visible
- * column headers. The table must be set in either
- * <code>ROW_HEADER_MODE_EXPLICIT</code> or
- * <code>ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID</code> mode to show the
- * headers with icons.
- * </p>
- *
- * @return Array of icons that match the <code>getVisibleColumns()</code>.
- */
- public Resource[] getColumnIcons() {
- if (this.columnIcons == null) {
- return null;
- }
- Resource[] icons = new Resource[this.visibleColumns.size()];
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) {
- icons[i] = (Resource) this.columnIcons.get(it.next());
- }
-
- return icons;
- }
-
- /**
- * Set the icons of the columns.
- *
- * <p>
- * The icons in headers match the property id:s given my the set visible
- * column headers. The table must be set in either
- * <code>ROW_HEADER_MODE_EXPLICIT</code> or
- * <code>ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID</code> mode to show the
- * headers with icons.
- * </p>
- *
- * @param columnIcons
- * Array of icons that match the <code>getVisibleColumns()</code>.
- */
- public void setColumnIcons(Resource[] columnIcons) {
-
- if (columnIcons.length != this.visibleColumns.size())
- throw new IllegalArgumentException(
- "The length of the icons array must match the number of visible columns");
-
- this.columnIcons.clear();
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext()
- && i < columnIcons.length; i++) {
- this.columnIcons.put(it.next(), columnIcons[i]);
- }
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Get array of column alignments.
- *
- * <p>
- * The items in the array must match the properties identified by
- * <code>getVisibleColumns()</code>. The possible values for the
- * alignments include:
- * <ul>
- * <li><code>ALIGN_LEFT</code>: Left alignment</li>
- * <li><code>ALIGN_CENTER</code>: Centered</li>
- * <li><code>ALIGN_RIGHT</code>: Right alignment</li>
- * </ul>
- * The alignments default to <code>ALIGN_LEFT</code>: any null values are
- * rendered as align lefts.
- * </p>
- *
- * @return Column alignments array.
- */
- public String[] getColumnAlignments() {
- if (this.columnAlignments == null) {
- return null;
- }
- String[] alignments = new String[this.visibleColumns.size()];
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) {
- alignments[i++] = getColumnAlignment(it.next());
- }
-
- return alignments;
- }
-
- /**
- * Set the column alignments.
- *
- * <p>
- * The items in the array must match the properties identified by
- * <code>getVisibleColumns()</code>. The possible values for the
- * alignments include:
- * <ul>
- * <li><code>ALIGN_LEFT</code>: Left alignment</li>
- * <li><code>ALIGN_CENTER</code>: Centered</li>
- * <li><code>ALIGN_RIGHT</code>: Right alignment</li>
- * </ul>
- * The alignments default to <code>ALIGN_LEFT</code>
- * </p>
- *
- * @param columnAlignments
- * Column alignments array.
- */
- public void setColumnAlignments(String[] columnAlignments) {
-
- if (columnAlignments.length != this.visibleColumns.size())
- throw new IllegalArgumentException(
- "The length of the alignments array must match the number of visible columns");
-
- // Check all alignments
- for (int i = 0; i < columnAlignments.length; i++) {
- String a = columnAlignments[i];
- if (a != null && !a.equals(ALIGN_LEFT) && !a.equals(ALIGN_CENTER)
- && !a.equals(ALIGN_RIGHT))
- throw new IllegalArgumentException("Column " + i
- + " aligment '" + a + "' is invalid");
- }
-
- // Reset alignments
- HashMap newCA = new HashMap();
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext()
- && i < columnAlignments.length; i++) {
- newCA.put(it.next(), columnAlignments[i]);
- }
- this.columnAlignments = newCA;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Get the page length.
- *
- * <p>
- * Setting page length 0 disables paging.
- * </p>
- *
- * @return Lenght of one page.
- */
- public int getPageLength() {
- return this.pageLength;
- }
-
- /**
- * Set the page length.
- *
- * <p>
- * Setting page length 0 disables paging. The page length defaults to 0 (no
- * paging).
- * </p>
- *
- * @param Lenght
- * of one page.
- */
- public void setPageLength(int pageLength) {
- if (pageLength >= 0 && this.pageLength != pageLength) {
- this.pageLength = pageLength;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
- }
-
- /**
- * Getter for property currentPageFirstItem.
- *
- * @return Value of property currentPageFirstItem.
- */
- public Object getCurrentPageFirstItemId() {
-
- // Priorise index over id if indexes are supported
- if (items instanceof Container.Indexed) {
- int index = getCurrentPageFirstItemIndex();
- Object id = null;
- if (index >= 0 && index < size())
- id = ((Container.Indexed) items).getIdByIndex(index);
- if (id != null && !id.equals(currentPageFirstItemId))
- currentPageFirstItemId = id;
- }
-
- // If there is no item id at all, use the first one
- if (currentPageFirstItemId == null)
- currentPageFirstItemId = ((Container.Ordered) items).firstItemId();
-
- return currentPageFirstItemId;
- }
-
- /**
- * Setter for property currentPageFirstItem.
- *
- * @param currentPageFirstItem
- * New value of property currentPageFirstItem.
- */
- public void setCurrentPageFirstItemId(Object currentPageFirstItemId) {
-
- // Get the corresponding index
- int index = -1;
- try {
- index = ((Container.Indexed) items)
- .indexOfId(currentPageFirstItemId);
- } catch (ClassCastException e) {
-
- // If the table item container does not have index, we have to
- // calculate the index by hand
- Object id = ((Container.Ordered) items).firstItemId();
- while (id != null && !id.equals(currentPageFirstItemId)) {
- index++;
- id = ((Container.Ordered) items).nextItemId(id);
- }
- if (id == null)
- index = -1;
- }
-
- // If the search for item index was successfull
- if (index >= 0) {
- this.currentPageFirstItemId = currentPageFirstItemId;
- this.currentPageFirstItemIndex = index;
- }
-
- // Assure visual refresh
- refreshCurrentPage();
-
- }
-
- /**
- * Gets the icon Resource for the specified column.
- *
- * @param propertyId
- * the propertyId indentifying the column.
- * @return the icon for the specified column; null if the column has no icon
- * set, or if the column is not visible.
- */
- public Resource getColumnIcon(Object propertyId) {
- return (Resource) this.columnIcons.get(propertyId);
- }
-
- /**
- * Sets the icon Resource for the specified column.
- * <p>
- * Throws IllegalArgumentException if the specified column is not visible.
- * </p>
- *
- * @param propertyId
- * the propertyId identifying the column.
- * @param icon
- * the icon Resource to set.
- */
- public void setColumnIcon(Object propertyId, Resource icon) {
-
- if (icon == null)
- this.columnIcons.remove(propertyId);
- else
- this.columnIcons.put(propertyId, icon);
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Gets the header for the specified column.
- *
- * @param propertyId
- * the propertyId indentifying the column.
- * @return the header for the specifed column if it has one.
- */
- public String getColumnHeader(Object propertyId) {
- if (getColumnHeaderMode() == COLUMN_HEADER_MODE_HIDDEN)
- return null;
-
- String header = (String) this.columnHeaders.get(propertyId);
- if ((header == null && this.getColumnHeaderMode() == COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID)
- || this.getColumnHeaderMode() == COLUMN_HEADER_MODE_ID) {
- header = propertyId.toString();
- }
-
- return header;
- }
-
- /**
- * Sets column header for the specified column;
- *
- * @param propertyId
- * the propertyId indentifying the column.
- * @param header
- * the header to set.
- */
- public void setColumnHeader(Object propertyId, String header) {
-
- if (header == null) {
- this.columnHeaders.remove(propertyId);
- return;
- }
- this.columnHeaders.put(propertyId, header);
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Gets the specified column's alignment.
- *
- * @param propertyId
- * the propertyID identifying the column.
- * @return the specified column's alignment if it as one; null otherwise.
- */
- public String getColumnAlignment(Object propertyId) {
- String a = (String) this.columnAlignments.get(propertyId);
- return a == null ? ALIGN_LEFT : a;
- }
-
- /**
- * Sets the specified column's alignment.
- *
- * <p>
- * Throws IllegalArgumentException if the alignment is not one of the
- * following: ALIGN_LEFT, ALIGN_CENTER or ALIGN_RIGHT
- * </p>
- *
- * @param propertyId
- * the propertyID identifying the column.
- * @param alignment
- * the desired alignment.
- */
- public void setColumnAlignment(Object propertyId, String alignment) {
-
- // Check for valid alignments
- if (alignment != null && !alignment.equals(ALIGN_LEFT)
- && !alignment.equals(ALIGN_CENTER)
- && !alignment.equals(ALIGN_RIGHT))
- throw new IllegalArgumentException("Column alignment '" + alignment
- + "' is not supported.");
-
- if (alignment == null || alignment.equals(ALIGN_LEFT)) {
- this.columnAlignments.remove(propertyId);
- return;
- }
-
- this.columnAlignments.put(propertyId, alignment);
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Checks if the specified column is collapsed.
- *
- * @param propertyId
- * the propertyID identifying the column.
- * @return true if the column is collapsed; false otherwise;
- */
- public boolean isColumnCollapsed(Object propertyId) {
- return collapsedColumns != null
- && collapsedColumns.contains(propertyId);
- }
-
- /**
- * Sets whether the specified column is collapsed or not.
- *
- *
- * @param propertyId
- * the propertyID identifying the column.
- * @param collapsed
- * the desired collapsedness.
- */
- public void setColumnCollapsed(Object propertyId, boolean collapsed)
- throws IllegalAccessException {
- if (!this.isColumnCollapsingAllowed()) {
- throw new IllegalAccessException("Column collapsing not allowed!");
- }
-
- if (collapsed)
- this.collapsedColumns.add(propertyId);
- else
- this.collapsedColumns.remove(propertyId);
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Check if column collapsing is allowed.
- *
- * @return true if columns can be collapsed; false otherwise.
- */
- public boolean isColumnCollapsingAllowed() {
- return this.columnCollapsingAllowed;
- }
-
- /**
- * Sets whether column collapsing is allowed or not.
- *
- * @param collapsingAllowed
- * specifies whether column collapsing is allowed.
- */
- public void setColumnCollapsingAllowed(boolean collapsingAllowed) {
- this.columnCollapsingAllowed = collapsingAllowed;
-
- if (!collapsingAllowed)
- collapsedColumns.clear();
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Check if column reordering is allowed.
- *
- * @return true if columns can be reordered; false otherwise.
- */
- public boolean isColumnReorderingAllowed() {
- return this.columnReorderingAllowed;
- }
-
- /**
- * Sets whether column reordering is allowed or not.
- *
- * @param reorderingAllowed
- * specifies whether column reordering is allowed.
- */
- public void setColumnReorderingAllowed(boolean reorderingAllowed) {
- this.columnReorderingAllowed = reorderingAllowed;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /*
- * Arranges visible columns according to given columnOrder. Silently ignores
- * colimnId:s that are not visible columns, and keeps the internal order of
- * visible columns left out of the ordering (trailing). Silently does
- * nothing if columnReordering is not allowed.
- */
- private void setColumnOrder(Object[] columnOrder) {
- if (columnOrder == null || !this.isColumnReorderingAllowed()) {
- return;
- }
- LinkedList newOrder = new LinkedList();
- for (int i = 0; i < columnOrder.length; i++) {
- if (columnOrder[i] != null
- && this.visibleColumns.contains(columnOrder[i])) {
- this.visibleColumns.remove(columnOrder[i]);
- newOrder.add(columnOrder[i]);
- }
- }
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext();) {
- Object columnId = it.next();
- if (!newOrder.contains(columnId))
- newOrder.add(columnId);
- }
- this.visibleColumns = newOrder;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Getter for property currentPageFirstItem.
- *
- * @return Value of property currentPageFirstItem.
- */
- public int getCurrentPageFirstItemIndex() {
- return this.currentPageFirstItemIndex;
- }
-
- /**
- * Setter for property currentPageFirstItem.
- *
- * @param newIndex
- * New value of property currentPageFirstItem.
- */
- public void setCurrentPageFirstItemIndex(int newIndex) {
-
- // Ensure that the new value is valid
- if (newIndex < 0)
- newIndex = 0;
- if (newIndex >= size())
- newIndex = size() - 1;
-
- // Refresh first item id
- if (items instanceof Container.Indexed) {
- try {
- currentPageFirstItemId = ((Container.Indexed) items)
- .getIdByIndex(newIndex);
- } catch (IndexOutOfBoundsException e) {
- currentPageFirstItemId = null;
- }
- this.currentPageFirstItemIndex = newIndex;
- } else {
-
- // For containers not supporting indexes, we must iterate the
- // container forwards / backwards
- // next available item forward or backward
-
- this.currentPageFirstItemId = ((Container.Ordered) items).firstItemId();
-
- // Go forwards in the middle of the list (respect borders)
- while (this.currentPageFirstItemIndex < newIndex
- && !((Container.Ordered) items)
- .isLastId(currentPageFirstItemId)) {
- this.currentPageFirstItemIndex++;
- currentPageFirstItemId = ((Container.Ordered) items)
- .nextItemId(currentPageFirstItemId);
- }
-
- // If we did hit the border
- if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) {
- this.currentPageFirstItemIndex = size() - 1;
- }
-
- // Go backwards in the middle of the list (respect borders)
- while (this.currentPageFirstItemIndex > newIndex
- && !((Container.Ordered) items)
- .isFirstId(currentPageFirstItemId)) {
- this.currentPageFirstItemIndex--;
- currentPageFirstItemId = ((Container.Ordered) items)
- .prevItemId(currentPageFirstItemId);
- }
-
- // If we did hit the border
- if (((Container.Ordered) items).isFirstId(currentPageFirstItemId)) {
- this.currentPageFirstItemIndex = 0;
- }
-
- // Go forwards once more
- while (this.currentPageFirstItemIndex < newIndex
- && !((Container.Ordered) items)
- .isLastId(currentPageFirstItemId)) {
- this.currentPageFirstItemIndex++;
- currentPageFirstItemId = ((Container.Ordered) items)
- .nextItemId(currentPageFirstItemId);
- }
-
- // If for some reason we do hit border again, override
- // the user index request
- if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) {
- newIndex = this.currentPageFirstItemIndex = size() - 1;
- }
- }
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Getter for property pageBuffering.
- *
- * @return Value of property pageBuffering.
- */
- public boolean isPageBufferingEnabled() {
- return this.pageBuffering;
- }
-
- /**
- * Setter for property pageBuffering.
- *
- * @param pageBuffering
- * New value of property pageBuffering.
- */
- public void setPageBufferingEnabled(boolean pageBuffering) {
-
- this.pageBuffering = pageBuffering;
-
- // If page buffering is disabled, clear the buffer
- if (!pageBuffering)
- pageBuffer = null;
- }
-
- /**
- * Getter for property selectable.
- *
- * <p>
- * The table is not selectable by default.
- * </p>
- *
- * @return Value of property selectable.
- */
- public boolean isSelectable() {
- return this.selectable;
- }
-
- /**
- * Setter for property selectable.
- *
- * <p>
- * The table is not selectable by default.
- * </p>
- *
- * @param selectable
- * New value of property selectable.
- */
- public void setSelectable(boolean selectable) {
- if (this.selectable != selectable) {
- this.selectable = selectable;
- requestRepaint();
- }
- }
-
- /**
- * Getter for property columnHeaderMode.
- *
- * @return Value of property columnHeaderMode.
- */
- public int getColumnHeaderMode() {
- return this.columnHeaderMode;
- }
-
- /**
- * Setter for property columnHeaderMode.
- *
- * @param columnHeaderMode
- * New value of property columnHeaderMode.
- */
- public void setColumnHeaderMode(int columnHeaderMode) {
- if (columnHeaderMode >= COLUMN_HEADER_MODE_HIDDEN
- && columnHeaderMode <= COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID)
- this.columnHeaderMode = columnHeaderMode;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Refresh the current page contents. If the page buffering is turned off,
- * it is not necessary to call this explicitely.
- */
- public void refreshCurrentPage() {
-
- // Clear page buffer and notify about the change
- pageBuffer = null;
- requestRepaint();
- }
-
- /**
- * Set the row header mode.
- * <p>
- * The mode can be one of the following ones:
- * <ul>
- * <li><code>ROW_HEADER_MODE_HIDDEN</code>: The row captions are hidden.
- * </li>
- * <li><code>ROW_HEADER_MODE_ID</code>: Items Id-objects
- * <code>toString()</code> is used as row caption.
- * <li><code>ROW_HEADER_MODE_ITEM</code>: Item-objects
- * <code>toString()</code> is used as row caption.
- * <li><code>ROW_HEADER_MODE_PROPERTY</code>: Property set with
- * <code>setItemCaptionPropertyId()</code> is used as row header.
- * <li><code>ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID</code>: Items
- * Id-objects <code>toString()</code> is used as row header. If caption is
- * explicitly specified, it overrides the id-caption.
- * <li><code>ROW_HEADER_MODE_EXPLICIT</code>: The row headers must be
- * explicitly specified.</li>
- * <li><code>ROW_HEADER_MODE_INDEX</code>: The index of the item is used
- * as row caption. The index mode can only be used with the containers
- * implementing <code>Container.Indexed</code> interface.</li>
- * </ul>
- * The default value is <code>ROW_HEADER_MODE_HIDDEN</code>
- * </p>
- *
- * @param mode
- * One of the modes listed above.
- */
- public void setRowHeaderMode(int mode) {
- if (ROW_HEADER_MODE_HIDDEN == mode)
- rowCaptionsAreHidden = true;
- else {
- rowCaptionsAreHidden = false;
- setItemCaptionMode(mode);
- }
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Get the row header mode.
- *
- * @return Row header mode.
- * @see #setRowHeaderMode(int)
- */
- public int getRowHeaderMode() {
- return rowCaptionsAreHidden ? ROW_HEADER_MODE_HIDDEN
- : getItemCaptionMode();
- }
-
- /**
- * Add new row to table and fill the visible cells with given values.
- *
- * @param cells
- * Object array that is used for filling the visible cells new
- * row. The types must be settable to visible column property
- * types.
- * @param itemId
- * Id the new row. If null, a new id is automatically assigned.
- * If given, the table cant already have a item with given id.
- * @return Returns item id for the new row. Returns null if operation fails.
- */
- public Object addItem(Object[] cells, Object itemId)
- throws UnsupportedOperationException {
-
- Object[] cols = getVisibleColumns();
-
- // Check that a correct number of cells are given
- if (cells.length != cols.length)
- return null;
-
- // Create new item
- Item item;
- if (itemId == null) {
- itemId = items.addItem();
- if (itemId == null)
- return null;
- item = items.getItem(itemId);
- } else
- item = items.addItem(itemId);
- if (item == null)
- return null;
-
- // Fill the item properties
- for (int i = 0; i < cols.length; i++)
- item.getItemProperty(cols[i]).setValue(cells[i]);
-
- return itemId;
- }
-
- /* Overriding select behavior******************************************** */
-
- /**
- * @see com.itmill.toolkit.data.Container.Viewer#setContainerDataSource(Container)
- */
- public void setContainerDataSource(Container newDataSource) {
-
- if (newDataSource == null)
- newDataSource = new IndexedContainer();
-
- // Assure that the data source is ordered by making unordered
- // containers ordered by wrapping them
- if (newDataSource instanceof Container.Ordered)
- super.setContainerDataSource(newDataSource);
- else
- super.setContainerDataSource(new ContainerOrderedWrapper(
- newDataSource));
-
- // Reset page position
- currentPageFirstItemId = null;
- currentPageFirstItemIndex = 0;
-
- // Reset column properties
- if (this.collapsedColumns != null)
- this.collapsedColumns.clear();
- setVisibleColumns(getContainerPropertyIds().toArray());
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /* Component basics ***************************************************** */
-
- /**
- * Invoked when the value of a variable has changed.
- *
- * @param event
- * Variable change event containing the information about the
- * changed variable.
- */
- public void changeVariables(Object source, Map variables) {
-
- super.changeVariables(source, variables);
-
- // Page start index
- if (variables.containsKey("firstvisible")) {
- Integer value = (Integer) variables.get("firstvisible");
- if (value != null)
- setCurrentPageFirstItemIndex(value.intValue() - 1);
- }
-
- // Set requested firstrow and rows for the next paint
- if (variables.containsKey("reqfirstrow") || variables.containsKey("reqrows")) {
- Integer value = (Integer) variables.get("reqfirstrow");
- if (value != null)
- reqFirstRowToPaint = value.intValue() -1;
- value = (Integer) variables.get("reqrows");
- if (value != null)
- reqRowsToPaint = value.intValue();
- pageBuffer = null;
- requestRepaint();
- }
-
- // Actions
- if (variables.containsKey("action")) {
- StringTokenizer st = new StringTokenizer((String) variables
- .get("action"), ",");
- if (st.countTokens() == 2) {
- Object itemId = itemIdMapper.get(st.nextToken());
- Action action = (Action) actionMapper.get(st.nextToken());
- if (action != null && containsId(itemId)
- && actionHandlers != null)
- for (Iterator i = actionHandlers.iterator(); i.hasNext();)
- ((Action.Handler) i.next()).handleAction(action, this,
- itemId);
- }
- }
-
- // Sorting
- boolean doSort = false;
- if (variables.containsKey("sortcolumn")) {
- String colId = (String) variables.get("sortcolumn");
- if (colId != null && !"".equals(colId) && !"null".equals(colId)) {
- Object id = this.columnIdMap.get(colId);
- setSortContainerPropertyId(id);
- doSort = true;
- }
- }
- if (variables.containsKey("sortascending")) {
- boolean state = ((Boolean) variables.get("sortascending"))
- .booleanValue();
- if (state != this.sortAscending) {
- setSortAscending(state);
- doSort = true;
- }
- }
- if (doSort)
- this.sort();
-
- // Dynamic column hide/show and order
- // Update visible columns
- if (this.isColumnCollapsingAllowed()) {
- if (variables.containsKey("collapsedcolumns")) {
- try {
- Object[] ids = (Object[]) variables.get("collapsedcolumns");
- for (Iterator it = this.visibleColumns.iterator(); it
- .hasNext();) {
- this.setColumnCollapsed(it.next(), false);
- }
- for (int i = 0; i < ids.length; i++) {
- this.setColumnCollapsed(columnIdMap.get(ids[i]
- .toString()), true);
- }
- } catch (Exception ignored) {
- }
- }
- }
- if (this.isColumnReorderingAllowed()) {
- if (variables.containsKey("columnorder")) {
- try {
- Object[] ids = (Object[]) variables.get("columnorder");
- for (int i = 0; i < ids.length; i++) {
- ids[i] = columnIdMap.get(ids[i].toString());
- }
- this.setColumnOrder(ids);
- } catch (Exception ignored) {
- }
- }
- }
- }
-
- /**
- * Paint the content of this component.
- *
- * @param target
- * Paint target.
- * @throws PaintException
- * The paint operation failed.
- */
- public void paintContent(PaintTarget target) throws PaintException {
-
- // Focus control id
- if (this.getFocusableId() > 0) {
- target.addAttribute("focusid", this.getFocusableId());
- }
-
- // The tab ordering number
- if (this.getTabIndex() > 0)
- target.addAttribute("tabindex", this.getTabIndex());
-
- // Size
- if (getHeight() >= 0)
- target.addAttribute("height", "" + getHeight() + Sizeable.UNIT_SYMBOLS[getHeightUnits()]);
- if (getWidth() >= 0)
- target.addAttribute("width", "" + getWidth()+ Sizeable.UNIT_SYMBOLS[getWidthUnits()]);
-
-
- // Initialize temps
- Object[] colids = getVisibleColumns();
- int cols = colids.length;
- int first = getCurrentPageFirstItemIndex();
- int total = size();
- int pagelen = getPageLength();
- int colHeadMode = getColumnHeaderMode();
- boolean colheads = colHeadMode != COLUMN_HEADER_MODE_HIDDEN;
- boolean rowheads = getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN;
- Object[][] cells = getVisibleCells();
- boolean iseditable = this.isEditable();
-
- // selection support
- String[] selectedKeys;
- if (isMultiSelect())
- selectedKeys = new String[((Set) getValue()).size()];
- else
- selectedKeys = new String[(getValue() == null
- && getNullSelectionItemId() == null ? 0 : 1)];
- int keyIndex = 0;
-
- // Table attributes
- if (isSelectable())
- target.addAttribute("selectmode", (isMultiSelect() ? "multi"
- : "single"));
- else
- target.addAttribute("selectmode", "none");
- target.addAttribute("cols", cols);
- target.addAttribute("rows", cells[0].length);
- target.addAttribute("firstrow", (reqFirstRowToPaint >= 0 ? reqFirstRowToPaint : first) + 1);
- target.addAttribute("totalrows", total);
- if (pagelen != 0)
- target.addAttribute("pagelength", pagelen);
- if (colheads)
- target.addAttribute("colheaders", true);
- if (rowheads)
- target.addAttribute("rowheaders", true);
-
- // Columns
- target.startTag("cols");
- Collection sortables = getSortableContainerPropertyIds();
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext();) {
- Object columnId = it.next();
- if (!isColumnCollapsed(columnId)) {
- target.startTag("ch");
- if (colheads) {
- if (this.getColumnIcon(columnId) != null)
- target.addAttribute("icon", this
- .getColumnIcon(columnId));
- if (sortables.contains(columnId))
- target.addAttribute("sortable", true);
- String header = (String) this.getColumnHeader(columnId);
- target.addAttribute("caption", (header != null ? header
- : ""));
- }
- target.addAttribute("cid", this.columnIdMap.key(columnId));
- if (!ALIGN_LEFT.equals(this.getColumnAlignment(columnId)))
- target.addAttribute("align", this
- .getColumnAlignment(columnId));
- target.endTag("ch");
- }
- }
- target.endTag("cols");
-
- // Rows
- Set actionSet = new LinkedHashSet();
- boolean selectable = isSelectable();
- boolean[] iscomponent = new boolean[this.visibleColumns.size()];
- int iscomponentIndex = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext()
- && iscomponentIndex < iscomponent.length;) {
- Object columnId = it.next();
- Class colType = getType(columnId);
- iscomponent[iscomponentIndex++] = colType != null
- && Component.class.isAssignableFrom(colType);
- }
- target.startTag("rows");
- for (int i = 0; i < cells[0].length; i++) {
- target.startTag("tr");
- Object itemId = cells[CELL_ITEMID][i];
-
- // tr attributes
- if (rowheads) {
- if (cells[CELL_ICON][i] != null)
- target.addAttribute("icon", (Resource) cells[CELL_ICON][i]);
- if (cells[CELL_HEADER][i] != null)
- target.addAttribute("caption",
- (String) cells[CELL_HEADER][i]);
- }
- if (actionHandlers != null || isSelectable()) {
- target.addAttribute("key", (String) cells[CELL_KEY][i]);
- if (isSelected(itemId) && keyIndex < selectedKeys.length) {
- target.addAttribute("selected", true);
- selectedKeys[keyIndex++] = (String) cells[CELL_KEY][i];
- }
- }
-
- // Actions
- if (actionHandlers != null) {
- target.startTag("al");
- for (Iterator ahi = actionHandlers.iterator(); ahi.hasNext();) {
- Action[] aa = ((Action.Handler) ahi.next()).getActions(
- itemId, this);
- if (aa != null)
- for (int ai = 0; ai < aa.length; ai++) {
- String key = actionMapper.key(aa[ai]);
- actionSet.add(aa[ai]);
- target.addSection("ak", key);
- }
- }
- target.endTag("al");
- }
-
- // cells
- int currentColumn = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); currentColumn++) {
- Object columnId = it.next();
- if (columnId == null || this.isColumnCollapsed(columnId))
- continue;
- if ((iscomponent[currentColumn] || iseditable)
- && Component.class.isInstance(cells[CELL_FIRSTCOL
- + currentColumn][i])) {
- Component c = (Component) cells[CELL_FIRSTCOL
- + currentColumn][i];
- if (c == null)
- target.addSection("label", "");
- else
- c.paint(target);
- } else
- target.addSection("label", (String) cells[CELL_FIRSTCOL
- + currentColumn][i]);
- }
-
- target.endTag("tr");
- }
- target.endTag("rows");
-
- // The select variable is only enabled if selectable
- if (selectable)
- target.addVariable(this, "selected", selectedKeys);
-
- // The cursors are only shown on pageable table
- if (first != 0 || getPageLength() > 0)
- target.addVariable(this, "firstvisible", first + 1);
-
- // Sorting
- if (getContainerDataSource() instanceof Container.Sortable) {
- target.addVariable(this, "sortcolumn", this.columnIdMap.key(this.sortContainerPropertyId));
- target.addVariable(this, "sortascending", this.sortAscending);
- }
-
- // Reset and paint "to be painted next" variables. Also reset pageBuffer
- reqFirstRowToPaint = -1;
- reqRowsToPaint = -1;
- pageBuffer = null;
- target.addVariable(this, "reqrows", reqRowsToPaint);
- target.addVariable(this, "reqfirstrow", reqFirstRowToPaint);
-
- // Actions
- if (!actionSet.isEmpty()) {
- target.startTag("actions");
- target.addVariable(this, "action", "");
- for (Iterator it = actionSet.iterator(); it.hasNext();) {
- Action a = (Action) it.next();
- target.startTag("action");
- if (a.getCaption() != null)
- target.addAttribute("caption", a.getCaption());
- if (a.getIcon() != null)
- target.addAttribute("icon", a.getIcon());
- target.addAttribute("key", actionMapper.key(a));
- target.endTag("action");
- }
- target.endTag("actions");
- }
- if (this.columnReorderingAllowed) {
- String[] colorder = new String[this.visibleColumns.size()];
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext()
- && i < colorder.length;) {
- colorder[i++] = this.columnIdMap.key(it.next());
- }
- target.addVariable(this, "columnorder", colorder);
- }
- // Available columns
- if (this.columnCollapsingAllowed) {
- HashSet ccs = new HashSet();
- for (Iterator i = visibleColumns.iterator(); i.hasNext();) {
- Object o = i.next();
- if (isColumnCollapsed(o))
- ccs.add(o);
- }
- String[] collapsedkeys = new String[ccs.size()];
- int nextColumn = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext()
- && nextColumn < collapsedkeys.length;) {
- Object columnId = it.next();
- if (this.isColumnCollapsed(columnId)) {
- collapsedkeys[nextColumn++] = this.columnIdMap
- .key(columnId);
- }
- }
- target.addVariable(this, "collapsedcolumns", collapsedkeys);
- target.startTag("visiblecolumns");
- int i = 0;
- for (Iterator it = this.visibleColumns.iterator(); it.hasNext(); i++) {
- Object columnId = it.next();
- if (columnId != null) {
- target.startTag("column");
- target.addAttribute("cid", this.columnIdMap.key(columnId));
- String head = getColumnHeader(columnId);
- target.addAttribute("caption", (head != null ? head : ""));
- if (this.isColumnCollapsed(columnId)) {
- target.addAttribute("collapsed", true);
- }
- target.endTag("column");
- }
- }
- target.endTag("visiblecolumns");
- }
- }
-
- /**
- * Get UIDL tag corresponding to component.
- *
- * @return UIDL tag as string.
- */
- public String getTag() {
- return "table";
- }
-
- /** Return cached visible table contents */
- private Object[][] getVisibleCells() {
-
- // Return a buffered value if possible
- if (pageBuffer != null && isPageBufferingEnabled())
- return pageBuffer;
-
- // Stop listening the old properties and initialise the list
- if (listenedProperties == null)
- listenedProperties = new LinkedList();
- else
- for (Iterator i = listenedProperties.iterator(); i.hasNext();) {
- ((Property.ValueChangeNotifier) i.next()).removeListener(this);
- }
-
- // Detach old visible component from the table
- if (visibleComponents == null)
- visibleComponents = new LinkedList();
- else
- for (Iterator i = visibleComponents.iterator(); i.hasNext();) {
- ((Component) i.next()).setParent(null);
- }
-
- // Collect basic facts about the table page
- Object[] colids = getVisibleColumns();
- int cols = colids.length;
- int pagelen = getPageLength();
- int firstIndex = getCurrentPageFirstItemIndex();
- int rows = size();
- if (rows > 0 && firstIndex >= 0)
- rows -= firstIndex;
- if (pagelen > 0 && pagelen < rows)
- rows = pagelen;
-
- // If "to be painted next" variables are set, use them
- if (reqRowsToPaint >= 0) rows = reqRowsToPaint;
- Object id;
- if (reqFirstRowToPaint >= 0 && reqFirstRowToPaint < size())
- firstIndex = reqFirstRowToPaint;
- if (rows + firstIndex > size()) rows = size() - firstIndex;
-
- // Get first item id
- if (items instanceof Container.Indexed)
- id = ((Container.Indexed) items).getIdByIndex(firstIndex);
- else {
- id = ((Container.Ordered) items).firstItemId();
- for (int i=0; i<firstIndex; i++) id = ((Container.Ordered) items).nextItemId(id);
- }
-
- Object[][] cells = new Object[cols + CELL_FIRSTCOL][rows];
- if (rows == 0)
- return cells;
- int headmode = getRowHeaderMode();
- boolean[] iscomponent = new boolean[cols];
- for (int i = 0; i < cols; i++)
- iscomponent[i] = Component.class
- .isAssignableFrom(getType(colids[i]));
-
- // Create page contents
- int filledRows = 0;
- for (int i = 0; i < rows && id != null; i++) {
- cells[CELL_ITEMID][i] = id;
- cells[CELL_KEY][i] = itemIdMapper.key(id);
- if (headmode != ROW_HEADER_MODE_HIDDEN) {
- switch (headmode) {
- case ROW_HEADER_MODE_INDEX:
- cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1);
- break;
- default:
- cells[CELL_HEADER][i] = getItemCaption(id);
- }
- cells[CELL_ICON][i] = getItemIcon(id);
- }
- if (cols > 0) {
- for (int j = 0; j < cols; j++) {
- Object value = null;
- Property p = getContainerProperty(id, colids[j]);
- if (p != null) {
- if (p instanceof Property.ValueChangeNotifier) {
- ((Property.ValueChangeNotifier) p)
- .addListener(this);
- listenedProperties.add(p);
- }
- if (iscomponent[j]) {
- value = p.getValue();
- } else if (p != null) {
- value = getPropertyValue(id, colids[j], p);
- } else {
- value = getPropertyValue(id, colids[j], null);
- }
- } else {
- value = "";
- }
-
- if (value instanceof Component) {
- ((Component) value).setParent(this);
- visibleComponents.add((Component) value);
- }
- cells[CELL_FIRSTCOL + j][i] = value;
-
- }
- }
- id = ((Container.Ordered) items).nextItemId(id);
-
- filledRows++;
- }
-
- // Assure that all the rows of the cell-buffer are valid
- if (filledRows != cells[0].length) {
- Object[][] temp = new Object[cells.length][filledRows];
- for (int i = 0; i < cells.length; i++)
- for (int j = 0; j < filledRows; j++)
- temp[i][j] = cells[i][j];
- cells = temp;
- }
-
- // Save the results to internal buffer iff in buffering mode
- // to possible conserve memory from large non-buffered pages
- if (isPageBufferingEnabled())
- pageBuffer = cells;
-
- return cells;
- }
-
- /**
- * Get value of property.
- *
- * By default if the table is editable the fieldFactory is used to create
- * editors for table cells. Otherwise formatPropertyValue is used to format
- * the value representation.
- *
- * @see #setFieldFactory(FieldFactory)
- * @param rowId
- * Id of the row (same as item Id)
- * @param colId
- * Id of the column
- * @param property
- * Property to be presented
- * @return Object Either formatted value or Component for field.
- */
- protected Object getPropertyValue(Object rowId, Object colId,
- Property property) {
- if (this.isEditable() && this.fieldFactory != null) {
- Field f = this.fieldFactory.createField(getContainerDataSource(),
- rowId, colId, this);
- if (f != null) {
- f.setPropertyDataSource(property);
- return f;
- }
- }
-
- return formatPropertyValue(rowId, colId, property);
- }
-
- /**
- * Formats table cell property values. By default the property.toString()
- * and return a empty string for null properties.
- *
- * @param itemId
- * @param property
- * Property to be formatted
- * @return String representation of property and its value.
- * @since 3.1
- */
- protected String formatPropertyValue(Object rowId, Object colId,
- Property property) {
- if (property == null) {
- return "";
- }
- return property.toString();
- }
-
- /* Action container *************************************************** */
-
- /**
- * @see com.itmill.toolkit.event.Action.Container#addActionHandler(Action.Handler)
- */
- public void addActionHandler(Action.Handler actionHandler) {
-
- if (actionHandler != null) {
-
- if (actionHandlers == null) {
- actionHandlers = new LinkedList();
- actionMapper = new KeyMapper();
- }
-
- if(!actionHandlers.contains(actionHandler)){
- actionHandlers.add(actionHandler);
- requestRepaint();
- }
-
- }
- }
-
- /**
- * @see com.itmill.toolkit.event.Action.Container#removeActionHandler(Action.Handler)
- */
- public void removeActionHandler(Action.Handler actionHandler) {
-
- if (actionHandlers != null && actionHandlers.contains(actionHandler)) {
-
- actionHandlers.remove(actionHandler);
-
- if (actionHandlers.isEmpty()) {
- actionHandlers = null;
- actionMapper = null;
- }
-
- requestRepaint();
- }
- }
-
- /* Property value change listening support **************************** */
-
- /**
- * @see com.itmill.toolkit.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
- */
- public void valueChange(Property.ValueChangeEvent event) {
- super.valueChange(event);
- requestRepaint();
- }
-
- /**
- * @see com.itmill.toolkit.ui.Component#attach()
- */
- public void attach() {
- super.attach();
-
- if (visibleComponents != null)
- for (Iterator i = visibleComponents.iterator(); i.hasNext();)
- ((Component) i.next()).attach();
- }
-
- /**
- * @see com.itmill.toolkit.ui.Component#attach()
- */
- public void detach() {
- super.detach();
-
- if (visibleComponents != null)
- for (Iterator i = visibleComponents.iterator(); i.hasNext();)
- ((Component) i.next()).detach();
- }
-
- /**
- * @see com.itmill.toolkit.data.Container#removeAllItems()
- */
- public boolean removeAllItems() {
- this.currentPageFirstItemId = null;
- this.currentPageFirstItemIndex = 0;
- return super.removeAllItems();
- }
-
- /**
- * @see com.itmill.toolkit.data.Container#removeItem(Object)
- */
- public boolean removeItem(Object itemId) {
- Object nextItemId = ((Container.Ordered) items).nextItemId(itemId);
- boolean ret = super.removeItem(itemId);
- if (ret && (itemId != null)
- && (itemId.equals(this.currentPageFirstItemId))) {
- this.currentPageFirstItemId = nextItemId;
- }
- return ret;
- }
-
- /**
- * @see com.itmill.toolkit.data.Container#removeContainerProperty(Object)
- */
- public boolean removeContainerProperty(Object propertyId)
- throws UnsupportedOperationException {
-
- // If a visible property is removed, remove the corresponding column
- this.visibleColumns.remove(propertyId);
- this.columnAlignments.remove(propertyId);
- this.columnIcons.remove(propertyId);
- this.columnHeaders.remove(propertyId);
-
- return super.removeContainerProperty(propertyId);
- }
-
- /**
- * Adds a new property to the table and show it as a visible column.
- *
- * @see com.itmill.toolkit.data.Container#addContainerProperty(Object,
- * Class, Object)
- *
- * @param propertyId
- * Id of the proprty
- * @param type
- * The class of the property
- * @param defaultValue
- * The default value given for all existing items
- */
- public boolean addContainerProperty(Object propertyId, Class type,
- Object defaultValue) throws UnsupportedOperationException {
- if (!super.addContainerProperty(propertyId, type, defaultValue))
- return false;
- if (!this.visibleColumns.contains(propertyId))
- this.visibleColumns.add(propertyId);
- return true;
- }
-
- /**
- * Adds a new property to the table and show it as a visible column.
- *
- * @see com.itmill.toolkit.data.Container#addContainerProperty(Object,
- * Class, Object)
- *
- * @param propertyId
- * Id of the proprty
- * @param type
- * The class of the property
- * @param defaultValue
- * The default value given for all existing items
- * @param columnHeader
- * Explicit header of the column. If explicit header is not
- * needed, this should be set null.
- * @param columnIcon
- * Icon of the column. If icon is not needed, this should be set
- * null.
- * @param columnAlignment
- * Alignment of the column. Null implies align left.
- */
- public boolean addContainerProperty(Object propertyId, Class type,
- Object defaultValue, String columnHeader, Resource columnIcon,
- String columnAlignment) throws UnsupportedOperationException {
- if (!this.addContainerProperty(propertyId, type, defaultValue))
- return false;
- this.setColumnAlignment(propertyId, columnAlignment);
- this.setColumnHeader(propertyId, columnHeader);
- this.setColumnIcon(propertyId, columnIcon);
- return true;
- }
-
- /**
- * Return list of items on the current page
- *
- * @see com.itmill.toolkit.ui.Select#getVisibleItemIds()
- */
- public Collection getVisibleItemIds() {
-
- LinkedList visible = new LinkedList();
-
- Object[][] cells = getVisibleCells();
- for (int i = 0; i < cells[CELL_ITEMID].length; i++)
- visible.add(cells[CELL_ITEMID][i]);
-
- return visible;
- }
-
- /**
- * Container datasource item set change. Table must flush its buffers on
- * change.
- *
- * @see com.itmill.toolkit.data.Container.ItemSetChangeListener#containerItemSetChange(com.itmill.toolkit.data.Container.ItemSetChangeEvent)
- */
- public void containerItemSetChange(Container.ItemSetChangeEvent event) {
- pageBuffer = null;
- super.containerItemSetChange(event);
- setCurrentPageFirstItemIndex(this.getCurrentPageFirstItemIndex());
- }
-
- /**
- * Container datasource property set change. Table must flush its buffers on
- * change.
- *
- * @see com.itmill.toolkit.data.Container.PropertySetChangeListener#containerPropertySetChange(com.itmill.toolkit.data.Container.PropertySetChangeEvent)
- */
- public void containerPropertySetChange(
- Container.PropertySetChangeEvent event) {
- pageBuffer = null;
- super.containerPropertySetChange(event);
- }
-
- /**
- * Adding new items is not supported.
- *
- * @see com.itmill.toolkit.ui.Select#setNewItemsAllowed(boolean)
- * @throws UnsupportedOperationException
- * if set to true.
- */
- public void setNewItemsAllowed(boolean allowNewOptions)
- throws UnsupportedOperationException {
- if (allowNewOptions)
- throw new UnsupportedOperationException();
- }
-
- /**
- * Focusing to this component is not supported.
- *
- * @see com.itmill.toolkit.ui.AbstractField#focus()
- * @throws UnsupportedOperationException
- * if invoked.
- */
- public void focus() throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#nextItemId(java.lang.Object)
- */
- public Object nextItemId(Object itemId) {
- return ((Container.Ordered) items).nextItemId(itemId);
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#prevItemId(java.lang.Object)
- */
- public Object prevItemId(Object itemId) {
- return ((Container.Ordered) items).prevItemId(itemId);
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#firstItemId()
- */
- public Object firstItemId() {
- return ((Container.Ordered) items).firstItemId();
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#lastItemId()
- */
- public Object lastItemId() {
- return ((Container.Ordered) items).lastItemId();
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#isFirstId(java.lang.Object)
- */
- public boolean isFirstId(Object itemId) {
- return ((Container.Ordered) items).isFirstId(itemId);
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#isLastId(java.lang.Object)
- */
- public boolean isLastId(Object itemId) {
- return ((Container.Ordered) items).isLastId(itemId);
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(java.lang.Object)
- */
- public Object addItemAfter(Object previousItemId)
- throws UnsupportedOperationException {
- return ((Container.Ordered) items).addItemAfter(previousItemId);
- }
-
- /**
- * @see com.itmill.toolkit.data.Container.Ordered#addItemAfter(java.lang.Object,
- * java.lang.Object)
- */
- public Item addItemAfter(Object previousItemId, Object newItemId)
- throws UnsupportedOperationException {
- return ((Container.Ordered) items).addItemAfter(previousItemId,
- newItemId);
- }
-
- /**
- * Get the FieldFactory that is used to create editor for table cells.
- *
- * The FieldFactory is only used if the Table is editable.
- *
- * @see #isEditable
- * @return FieldFactory used to create the Field instances.
- */
- public FieldFactory getFieldFactory() {
- return fieldFactory;
- }
-
- /**
- * Set the FieldFactory that is used to create editor for table cells.
- *
- * The FieldFactory is only used if the Table is editable. By default the
- * BaseFieldFactory is used.
- *
- * @see #isEditable
- * @see BaseFieldFactory
- * @param fieldFactory
- * The field factory to set
- */
- public void setFieldFactory(FieldFactory fieldFactory) {
- this.fieldFactory = fieldFactory;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Is table editable.
- *
- * If table is editable a editor of type Field is created for each table
- * cell. The assigned FieldFactory is used to create the instances.
- *
- * To provide custom editors for table cells create a class implementins the
- * FieldFactory interface, and assign it to table, and set the editable
- * property to true.
- *
- * @see Field
- * @see FieldFactory
- * @return true if table is editable, false oterwise.
- */
- public boolean isEditable() {
- return editable;
- }
-
- /**
- * Set the editable property.
- *
- * If table is editable a editor of type Field is created for each table
- * cell. The assigned FieldFactory is used to create the instances.
- *
- * To provide custom editors for table cells create a class implementins the
- * FieldFactory interface, and assign it to table, and set the editable
- * property to true.
- *
- * @see Field
- * @see FieldFactory
- * @param editable
- * true if table should be editable by user.
- */
- public void setEditable(boolean editable) {
- this.editable = editable;
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Sort table.
- *
- * @see com.itmill.toolkit.data.Container.Sortable#sort(java.lang.Object[],
- * boolean[])
- *
- * @throws UnsupportedOperationException
- * if the container data source does not implement
- * Container.Sortable
- */
- public void sort(Object[] propertyId, boolean[] ascending)
- throws UnsupportedOperationException {
- Container c = getContainerDataSource();
- if (c instanceof Container.Sortable) {
- int pageIndex = this.getCurrentPageFirstItemIndex();
- ((Container.Sortable) c).sort(propertyId, ascending);
- setCurrentPageFirstItemIndex(pageIndex);
- } else if (c != null) {
- throw new UnsupportedOperationException(
- "Underlying Data does not allow sorting");
- }
- }
-
- /**
- * Sort table by currently selected sorting column.
- *
- * @throws UnsupportedOperationException
- * if the container data source does not implement
- * Container.Sortable
- */
- public void sort() {
- if (getSortContainerPropertyId() == null)
- return;
- sort(new Object[] { this.sortContainerPropertyId },
- new boolean[] { this.sortAscending });
- }
-
- /*
- * (non-Javadoc)
- *
- * @see com.itmill.toolkit.data.Container.Sortable#getSortableContainerPropertyIds()
- */
- public Collection getSortableContainerPropertyIds() {
- Container c = getContainerDataSource();
- if (c instanceof Container.Sortable && !isSortDisabled()) {
- return ((Container.Sortable) c).getSortableContainerPropertyIds();
- } else {
- return new LinkedList();
- }
- }
-
- /**
- * Get the currently sorted column property ID.
- *
- * @return Container property id of the currently sorted column.
- */
- public Object getSortContainerPropertyId() {
- return this.sortContainerPropertyId;
- }
-
- /**
- * Set the currently sorted column property id.
- *
- * @param propertyId
- * Container property id of the currently sorted column.
- */
- public void setSortContainerPropertyId(Object propertyId) {
- if ((this.sortContainerPropertyId != null && !this.sortContainerPropertyId
- .equals(propertyId))
- || (this.sortContainerPropertyId == null && propertyId != null)) {
- this.sortContainerPropertyId = propertyId;
- sort();
- }
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /**
- * Is the table currently sorted in ascending order.
- *
- * @return <code>true</code> if ascending, <code>false</code> if
- * descending
- */
- public boolean isSortAscending() {
- return this.sortAscending;
- }
-
- /**
- * Set the table in ascending order.
- *
- * @param ascending
- * <code>true</code> if ascending, <code>false</code> if
- * descending
- */
- public void setSortAscending(boolean ascending) {
- if (this.sortAscending != ascending) {
- this.sortAscending = ascending;
- sort();
- }
-
- // Assure visual refresh
- refreshCurrentPage();
- }
-
- /** Is sorting disabled alltogether.
- *
- * True iff no sortable columns are given even in the case where datasource would support this.
- *
- * @return True iff sorting is disabled.
- */
- public boolean isSortDisabled() {
- return sortDisabled;
- }
-
-
- /** Disable sorting alltogether.
- *
- * To disable sorting alltogether, set to true. In this case no
- * sortable columns are given even in the case where datasource would support this.
- *
- * @param sortDisabled True iff sorting is disabled
- */
- public void setSortDisabled(boolean sortDisabled) {
- if (this.sortDisabled != sortDisabled) {
- this.sortDisabled = sortDisabled;
- refreshCurrentPage();
- }
- }
-
- /**
- * @see com.itmill.toolkit.terminal.Sizeable#getHeightUnits()
- */
- public int getHeightUnits() {
- return heightUnit;
- }
-
- /**
- * @see com.itmill.toolkit.terminal.Sizeable#getWidthUnits()
- */
- public int getWidthUnits() {
- return widthUnit;
- }
-
- /** Set height units.
- * Table supports only Sizeable.UNITS_PIXELS. Setting to any other throws
- * IllegalArgumentException.
- * @see com.itmill.toolkit.terminal.Sizeable#setHeightUnits(int)
- */
- public void setHeightUnits(int units) {
- if (units != Sizeable.UNITS_PIXELS)
- throw new IllegalArgumentException();
- this.heightUnit = units;
- }
-
- /** Set width units.
- * Tabel supports only Sizeable.UNITS_PIXELS and Sizeable.UNITS_PERCENTAGE. Setting to any other throws
- * IllegalArgumentException.
- * @see com.itmill.toolkit.terminal.Sizeable#setWidthUnits(int)
- */
- public void setWidthUnits(int units) {
- if (units != Sizeable.UNITS_PIXELS && units != Sizeable.UNITS_PERCENTAGE)
- throw new IllegalArgumentException();
- this.widthUnit = units;
- }
-
- /**
- * @return The height in pixels or negative value if not assigned.
- */
- public int getHeight() {
- return height;
- }
-
- /**
- * @return The width in pixels or negative value if not assigned.
- */
- public int getWidth() {
- return width;
- }
-
- /** Sets the height in pixels.
- * Use negative value to let the client decide the height.
- * @param height The height to set
- */
- public void setHeight(int height) {
- this.height = height;
- requestRepaint();
- }
-
- /** Sets the width in pixels.
- * Use negative value to allow the client decide the width.
- * @param width The width to set
- */
- public void setWidth(int width) {
- this.width = width;
- requestRepaint();
- }
-
- /** Table does not support lazy options loading mode.
- * Setting this true will throw UnsupportedOperationException.
- */
- public void setLazyLoading(boolean useLazyLoading) {
- if (useLazyLoading)
- throw new UnsupportedOperationException("Lazy options loading is not supported by Table.");
- }
-
-
- }
|