org.unitime.timetable.gwt.client.rooms.RoomsTable.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.timetable.gwt.client.rooms.RoomsTable.java

Source

/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * The Apereo Foundation licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
*/
package org.unitime.timetable.gwt.client.rooms;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.unitime.timetable.gwt.client.ToolBox;
import org.unitime.timetable.gwt.client.aria.AriaCheckBox;
import org.unitime.timetable.gwt.client.page.UniTimePageHeader;
import org.unitime.timetable.gwt.client.widgets.ImageLink;
import org.unitime.timetable.gwt.client.widgets.P;
import org.unitime.timetable.gwt.client.widgets.UniTimeTable;
import org.unitime.timetable.gwt.client.widgets.UniTimeTableHeader;
import org.unitime.timetable.gwt.client.widgets.UniTimeTableHeader.AriaOperation;
import org.unitime.timetable.gwt.client.widgets.UniTimeTableHeader.HasColumnName;
import org.unitime.timetable.gwt.client.widgets.UniTimeTableHeader.Operation;
import org.unitime.timetable.gwt.command.client.GwtRpcService;
import org.unitime.timetable.gwt.command.client.GwtRpcServiceAsync;
import org.unitime.timetable.gwt.resources.GwtAriaMessages;
import org.unitime.timetable.gwt.resources.GwtConstants;
import org.unitime.timetable.gwt.resources.GwtMessages;
import org.unitime.timetable.gwt.resources.GwtResources;
import org.unitime.timetable.gwt.shared.RoomInterface.AttachmentTypeInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.DepartmentInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.ExamTypeInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.FeatureInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.FeatureTypeInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.GroupInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.RoomDetailInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.RoomPictureInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.RoomPropertiesInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.RoomPropertyInterface;
import org.unitime.timetable.gwt.shared.RoomInterface.RoomsColumn;
import org.unitime.timetable.gwt.shared.RoomInterface.RoomsPageMode;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.TakesValue;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

/**
 * @author Tomas Muller
 */
public class RoomsTable extends UniTimeTable<RoomDetailInterface> {
    protected static final GwtMessages MESSAGES = GWT.create(GwtMessages.class);
    protected static final GwtAriaMessages ARIA = GWT.create(GwtAriaMessages.class);
    protected static final GwtResources RESOURCES = GWT.create(GwtResources.class);
    protected static final GwtConstants CONSTANTS = GWT.create(GwtConstants.class);
    protected static final GwtRpcServiceAsync RPC = GWT.create(GwtRpcService.class);

    private int iFlags = 0;
    private RoomsColumn iSortBy = null;
    private boolean iAsc = true;
    private RoomsPageMode iMode = null;
    private String iDepartment = null;
    private List<Operation> iSortOperations = new ArrayList<Operation>();
    private List<Operation> iShowHideOperations = new ArrayList<Operation>();
    private List<Operation> iDepartmentOperations = new ArrayList<Operation>();
    private List<Operation> iOtherOperations = new ArrayList<Operation>();
    private RoomPropertiesInterface iProperties = null;
    private boolean iSelectable;

    public RoomsTable(RoomsPageMode mode, boolean selectable) {
        setStyleName("unitime-Rooms");
        iMode = mode;
        iSelectable = selectable;

        addOperation(new Operation() {

            @Override
            public void execute() {
                final RoomsTable table = new RoomsTable(iMode);
                table.setProperties(iProperties);
                table.setDepartment(iDepartment);
                for (int i = 1; i < getRowCount(); i++)
                    table.addRoom(getData(i));
                table.getElement().getStyle().setWidth(1040, Unit.PX);

                // Move header row to thead
                Element headerRow = table.getRowFormatter().getElement(0);
                Element tableElement = table.getElement();
                Element thead = DOM.createTHead();
                tableElement.insertFirst(thead);
                headerRow.getParentElement().removeChild(headerRow);
                thead.appendChild(headerRow);

                ToolBox.print(new ToolBox.Page() {
                    @Override
                    public String getName() {
                        return MESSAGES.pageRooms();
                    }

                    @Override
                    public String getUser() {
                        return UniTimePageHeader.getInstance().getMiddle().getText();
                    }

                    @Override
                    public String getSession() {
                        return UniTimePageHeader.getInstance().getRight().getText();
                    }

                    @Override
                    public Element getBody() {
                        return table.getElement();
                    }
                });
            }

            @Override
            public String getName() {
                return MESSAGES.buttonPrint();
            }

            @Override
            public boolean isApplicable() {
                return getRowCount() > 1 && !iSelectable;
            }

            @Override
            public boolean hasSeparator() {
                return true;
            }
        });
    }

    public RoomsTable(RoomsPageMode mode) {
        this(mode, false);
    }

    public RoomsTable(RoomsPageMode mode, RoomPropertiesInterface properties, boolean selectable) {
        this(mode, selectable);
        setProperties(properties);
    }

    public void setProperties(RoomPropertiesInterface properties) {
        iProperties = properties;

        super.clearTable();

        List<UniTimeTableHeader> header = new ArrayList<UniTimeTableHeader>();
        for (RoomsColumn column : RoomsColumn.values()) {
            int nrCells = getNbrCells(column);
            for (int idx = 0; idx < nrCells; idx++) {
                UniTimeTableHeader h = new UniTimeTableHeader(getColumnName(column, idx),
                        getColumnAlignment(column, idx));
                header.add(h);
            }
        }

        if (iSelectable) {
            header.get(0).addOperation(new Operation() {
                @Override
                public void execute() {
                    for (int row = 1; row < getRowCount(); row++) {
                        Widget w = getWidget(row, 0);
                        if (w != null && w instanceof CheckBox) {
                            CheckBox ch = (CheckBox) w;
                            ch.setValue(true);
                        }
                        setSelected(row, true);
                    }
                }

                @Override
                public boolean isApplicable() {
                    for (int row = 1; row < getRowCount(); row++) {
                        Widget w = getWidget(row, 0);
                        if (w != null && w instanceof CheckBox) {
                            CheckBox ch = (CheckBox) w;
                            if (!ch.getValue())
                                return true;
                        }
                    }
                    return false;
                }

                @Override
                public boolean hasSeparator() {
                    return false;
                }

                @Override
                public String getName() {
                    return MESSAGES.opSelectAll();
                }
            });
            header.get(0).addOperation(new Operation() {
                @Override
                public void execute() {
                    for (int row = 1; row < getRowCount(); row++) {
                        Widget w = getWidget(row, 0);
                        if (w != null && w instanceof CheckBox) {
                            CheckBox ch = (CheckBox) w;
                            ch.setValue(false);
                        }
                        setSelected(row, false);
                    }
                }

                @Override
                public boolean isApplicable() {
                    for (int row = 1; row < getRowCount(); row++) {
                        Widget w = getWidget(row, 0);
                        if (w != null && w instanceof CheckBox) {
                            CheckBox ch = (CheckBox) w;
                            if (ch.getValue())
                                return true;
                        }
                    }
                    return false;
                }

                @Override
                public boolean hasSeparator() {
                    return false;
                }

                @Override
                public String getName() {
                    return MESSAGES.opClearSelection();
                }
            });
        }

        if (RoomCookie.getInstance().getFlags(iMode) == 0) {
            int flags = 0;
            for (RoomsColumn column : RoomsColumn.values()) {
                if (iMode.hasColumn(column)) {
                    int nrCells = getNbrCells(column);
                    int cellIdx = getCellIndex(column);
                    for (int idx = 0; idx < nrCells; idx++) {
                        flags += (1 << (cellIdx + idx));
                    }
                }
            }
            RoomCookie.getInstance().setFlags(iMode, flags);
        }

        addRow(null, header);

        iShowHideOperations.clear();
        for (final RoomsColumn column : RoomsColumn.values()) {
            int nrCells = getNbrCells(column);
            int cellIdx = getCellIndex(column);
            for (int idx = 0; idx < nrCells; idx++) {
                final int colIdx = cellIdx + idx;
                final String cName = getColumnName(column, idx).replace("<br>", " ");
                UniTimeTableHeader h = header.get(colIdx);
                if (hasShowHideOperation(column)) {
                    Operation op = new AriaOperation() {
                        @Override
                        public void execute() {
                            boolean visible = isColumnVisible(colIdx);
                            setColumnVisible(colIdx, !visible);
                            RoomCookie.getInstance().set(iMode, colIdx, !visible);
                        }

                        @Override
                        public boolean isApplicable() {
                            return (iFlags & (1 << colIdx)) != 0;
                        }

                        @Override
                        public boolean hasSeparator() {
                            if (iSelectable && column == RoomsColumn.EXTERNAL_ID)
                                return true;
                            return false;
                        }

                        @Override
                        public String getName() {
                            return isColumnVisible(colIdx) ? MESSAGES.opHide(cName) : MESSAGES.opShow(cName);
                        }

                        @Override
                        public String getAriaLabel() {
                            return isColumnVisible(colIdx) ? ARIA.opHide(cName) : ARIA.opShow(cName);
                        }
                    };
                    iShowHideOperations.add(op);
                    if (colIdx > 0)
                        header.get(0).addOperation(op);
                    RoomsColumn g = getShowHideGroup(column);
                    if (g == null) {
                        h.addOperation(op);
                    } else {
                        for (RoomsColumn c : RoomsColumn.values()) {
                            if (g.equals(getShowHideGroup(c)))
                                for (int i = 0; i < getNbrCells(c); i++)
                                    header.get(getCellIndex(c) + i).addOperation(op);
                        }
                    }
                }
            }
        }

        iDepartmentOperations.clear();
        for (final DeptMode d : DeptMode.values()) {
            Operation op = new Operation() {
                @Override
                public void execute() {
                    RoomCookie.getInstance().setDeptMode(d.ordinal());
                    refreshTable();
                }

                @Override
                public boolean isApplicable() {
                    return getRowCount() > 0;
                }

                @Override
                public boolean hasSeparator() {
                    return d.ordinal() == 0;
                }

                @Override
                public String getName() {
                    if (RoomCookie.getInstance().getDeptMode() == d.ordinal())
                        return MESSAGES.opUncheck(d.getName());
                    else
                        return MESSAGES.opCheck(d.getName());
                }
            };
            iDepartmentOperations.add(op);
            for (RoomsColumn c : RoomsColumn.values()) {
                if (hasDepartmentOperation(c))
                    for (int i = 0; i < getNbrCells(c); i++)
                        header.get(getCellIndex(c) + i).addOperation(op);
            }
        }

        iSortOperations.clear();
        for (final RoomsColumn column : RoomsColumn.values()) {
            if (RoomsComparator.isApplicable(column)) {
                final UniTimeTableHeader h = header.get(getCellIndex(column));
                Operation op = new SortOperation() {
                    @Override
                    public void execute() {
                        if (column == iSortBy) {
                            iAsc = !iAsc;
                        } else {
                            iSortBy = column;
                            iAsc = true;
                        }
                        RoomCookie.getInstance().setSortRoomsBy(getSortBy());
                        sort();
                    }

                    @Override
                    public boolean isApplicable() {
                        return getRowCount() > 1 && h.isVisible();
                    }

                    @Override
                    public boolean hasSeparator() {
                        return true;
                    }

                    @Override
                    public String getName() {
                        return MESSAGES.opSortBy(getColumnName());
                    }

                    @Override
                    public String getColumnName() {
                        return h.getHTML().replace("<br>", " ");
                    }
                };
                iSortOperations.add(op);
                h.addOperation(op);
            }
        }

        for (Operation op : getOtherOperations())
            header.get(0).addOperation(op);

        for (int i = 0; i < getCellCount(0); i++)
            getCellFormatter().setStyleName(0, i, "unitime-ClickableTableHeader");

        resetVisibility();
        setSortBy(RoomCookie.getInstance().getRoomsSortBy());

        setVisible(false);

        if (iSelectable) {
            setAllowSelection(true);
            addMouseClickListener(new MouseClickListener<RoomDetailInterface>() {
                @Override
                public void onMouseClick(TableEvent<RoomDetailInterface> event) {
                    selectRoom(event.getRow(), isSelected(event.getRow()));
                }
            });
        }
    }

    public String getColumnName(RoomsColumn column, int idx) {
        switch (column) {
        case NAME:
            return MESSAGES.colName();
        case TYPE:
            return MESSAGES.colType();
        case EXTERNAL_ID:
            return MESSAGES.colExternalId();
        case CAPACITY:
            return MESSAGES.colCapacity();
        case EXAM_CAPACITY:
            return MESSAGES.colExaminationCapacity();
        case AREA:
            return MESSAGES.colArea(iProperties != null && iProperties.isRoomAreaInMetricUnits()
                    ? CONSTANTS.roomAreaMetricUnitsShort()
                    : CONSTANTS.roomAreaUnitsShort());
        case COORDINATES:
            return MESSAGES.colCoordinates();
        case DISTANCE_CHECK:
            return MESSAGES.colDistances();
        case ROOM_CHECK:
            return MESSAGES.colRoomCheck();
        case MAP:
            return MESSAGES.colMap();
        case PICTURES:
            if (idx == 0)
                return MESSAGES.colPictures();
            else
                return iProperties.getTableTypes().get(idx - 1).getAbbreviation();
        case PREFERENCE:
            return MESSAGES.colPreference();
        case AVAILABILITY:
            return MESSAGES.colAvailability();
        case DEPARTMENTS:
            return MESSAGES.colDepartments();
        case CONTROL_DEPT:
            return MESSAGES.colControl();
        case EXAM_TYPES:
            return MESSAGES.colExamTypes();
        case PERIOD_PREF:
            return MESSAGES.colPeriodPreferences();
        case EVENT_DEPARTMENT:
            return MESSAGES.colEventDepartment();
        case EVENT_STATUS:
            return MESSAGES.colEventStatus();
        case EVENT_AVAILABILITY:
            return MESSAGES.colEventAvailability();
        case EVENT_MESSAGE:
            return MESSAGES.colEventMessage();
        case BREAK_TIME:
            return MESSAGES.colBreakTime();
        case GROUPS:
            return MESSAGES.colGroups();
        case FEATURES:
            if (idx == 0)
                return MESSAGES.colFeatures();
            else
                return getFeatureType(idx - 1).getAbbreviation();
        default:
            return column.name();
        }
    }

    public void refreshTable() {
        for (int r = 1; r < getRowCount(); r++) {
            for (int c = 0; c < getCellCount(r); c++) {
                Widget w = getWidget(r, c);
                if (w instanceof HasRefresh)
                    ((HasRefresh) w).refresh();
            }
        }
    }

    protected HorizontalAlignmentConstant getColumnAlignment(RoomsColumn column, int idx) {
        switch (column) {
        case CAPACITY:
        case EXAM_CAPACITY:
        case AREA:
            return HasHorizontalAlignment.ALIGN_RIGHT;
        default:
            return HasHorizontalAlignment.ALIGN_LEFT;
        }
    }

    protected boolean hasShowHideOperation(RoomsColumn column) {
        switch (column) {
        case NAME:
            return false;
        default:
            return true;
        }
    }

    protected int getFlagOffset(RoomsColumn column) {
        switch (column) {
        case PICTURES:
            return countFeatureTypes();
        default:
            return 0;
        }
    }

    protected boolean hasDepartmentOperation(RoomsColumn column) {
        switch (column) {
        case DEPARTMENTS:
        case CONTROL_DEPT:
        case EVENT_DEPARTMENT:
            return true;
        default:
            return false;
        }
    }

    protected RoomsColumn getShowHideGroup(RoomsColumn column) {
        switch (column) {
        case EXTERNAL_ID:
        case TYPE:
            return RoomsColumn.EXTERNAL_ID;
        case CAPACITY:
        case EXAM_CAPACITY:
        case AREA:
        case COORDINATES:
        case DISTANCE_CHECK:
        case ROOM_CHECK:
            return RoomsColumn.CAPACITY;
        case PREFERENCE:
        case AVAILABILITY:
        case DEPARTMENTS:
        case CONTROL_DEPT:
            return RoomsColumn.PREFERENCE;
        case EVENT_DEPARTMENT:
        case EVENT_AVAILABILITY:
        case EVENT_STATUS:
        case EVENT_MESSAGE:
        case BREAK_TIME:
            return RoomsColumn.EVENT_DEPARTMENT;
        case EXAM_TYPES:
        case PERIOD_PREF:
            return RoomsColumn.EXAM_TYPES;
        case PICTURES:
            return RoomsColumn.PICTURES;
        case FEATURES:
            return RoomsColumn.FEATURES;
        default:
            return null;
        }
    }

    protected boolean hasFeatureTypes() {
        return iProperties != null && iProperties.getFeatureTypes() != null
                && !iProperties.getFeatureTypes().isEmpty();
    }

    protected int countFeatureTypes() {
        return iProperties == null ? 0 : iProperties.getFeatureTypes().size();
    }

    protected FeatureTypeInterface getFeatureType(int index) {
        return iProperties.getFeatureTypes().get(index);
    }

    public List<Operation> getSortOperations() {
        ArrayList<Operation> operations = new ArrayList<Operation>();
        for (Operation operation : iSortOperations)
            if (operation.isApplicable())
                operations.add(operation);
        return operations;
    }

    public List<Operation> getShowHideOperations() {
        ArrayList<Operation> operations = new ArrayList<Operation>();
        for (Operation operation : iShowHideOperations)
            if (operation.isApplicable())
                operations.add(operation);
        return operations;
    }

    public boolean hasDepartmentOperations() {
        return isVisible(RoomsColumn.EVENT_DEPARTMENT) || isVisible(RoomsColumn.DEPARTMENTS)
                || isVisible(RoomsColumn.CONTROL_DEPT);
    }

    public boolean hasOrientationOperations() {
        return isVisible(RoomsColumn.AVAILABILITY) || isVisible(RoomsColumn.PERIOD_PREF)
                || isVisible(RoomsColumn.EVENT_AVAILABILITY);
    }

    public List<Operation> getDepartmentOperations() {
        ArrayList<Operation> operations = new ArrayList<Operation>();
        for (Operation operation : iDepartmentOperations)
            if (operation.isApplicable())
                operations.add(operation);
        return operations;
    }

    public List<Operation> getOtherOperations() {
        ArrayList<Operation> operations = new ArrayList<Operation>();
        for (Operation operation : iOtherOperations)
            if (operation.isApplicable())
                operations.add(operation);
        return operations;
    }

    public boolean hasSortBy() {
        return iSortBy != null;
    }

    public int getSortBy() {
        return iSortBy == null ? 0 : iAsc ? 1 + iSortBy.ordinal() : -1 - iSortBy.ordinal();
    }

    public void setSortBy(int sortBy) {
        if (sortBy == 0) {
            iSortBy = null;
            iAsc = true;
        } else if (sortBy > 0) {
            iSortBy = RoomsColumn.values()[sortBy - 1];
            iAsc = true;
        } else {
            iSortBy = RoomsColumn.values()[-1 - sortBy];
            iAsc = false;
        }
        sort();
    }

    protected void addOperation(Operation op) {
        iOtherOperations.add(op);
    }

    public void sort() {
        if (iSortBy == null)
            return;
        Comparator<RoomDetailInterface> rc = null;
        if (iSelectable && iSortBy == RoomsColumn.NAME) {
            rc = new Comparator<RoomDetailInterface>() {
                private Comparator<RoomDetailInterface> iRC = new RoomsComparator(iSortBy, true);

                @Override
                public int compare(RoomDetailInterface r1, RoomDetailInterface r2) {
                    boolean s1 = isRoomSelected(r1), s2 = isRoomSelected(r2);
                    if (s1 != s2)
                        return s1 ? -1 : 1;
                    return iRC.compare(r1, r2);
                }
            };
        } else {
            rc = new RoomsComparator(iSortBy, true);
        }
        UniTimeTableHeader header = getHeader(getCellIndex(iSortBy));
        sort(header, rc, iAsc);
    }

    public void setDepartment(String department) {
        iDepartment = department;
    }

    protected int getNbrCells(RoomsColumn column) {
        switch (column) {
        case PICTURES:
            List<AttachmentTypeInterface> types = iProperties.getTableTypes();
            return 1 + (types == null ? 0 : types.size());
        case FEATURES:
            return 1 + iProperties.getFeatureTypes().size();
        default:
            return 1;
        }
    }

    protected int getCellIndex(RoomsColumn column) {
        int ret = 0;
        for (RoomsColumn c : RoomsColumn.values())
            if (c.ordinal() < column.ordinal())
                ret += getNbrCells(c);
        return ret;
    }

    protected Widget getCell(final RoomDetailInterface room, final RoomsColumn column, final int idx) {
        if (iProperties == null || !iProperties.isCanSeeCourses()) {
            switch (column) {
            case ROOM_CHECK:
                if (iProperties != null && iProperties.isCanSeeEvents())
                    break;
            case DISTANCE_CHECK:
            case PREFERENCE:
            case AVAILABILITY:
            case DEPARTMENTS:
            case CONTROL_DEPT:
                return null;
            }
        }
        if (iProperties == null || !iProperties.isCanSeeExams()) {
            switch (column) {
            case EXAM_CAPACITY:
            case EXAM_TYPES:
            case PERIOD_PREF:
                return null;
            }
        }
        if (iProperties == null || !iProperties.isCanSeeEvents()) {
            switch (column) {
            case EVENT_DEPARTMENT:
            case EVENT_MESSAGE:
            case EVENT_AVAILABILITY:
            case EVENT_STATUS:
            case BREAK_TIME:
                return null;
            }
        }
        switch (column) {
        case NAME:
            if (iSelectable) {
                return new SelectableRoomNameCell(room);
            } else {
                return new RoomNameCell(room);
            }

        case EXTERNAL_ID:
            if (!room.hasExternalId())
                return null;
            return new Label(room.getExternalId());

        case TYPE:
            return new Label(room.getRoomType().getLabel());

        case CAPACITY:
            if (room.getCapacity() == null)
                return null;
            return new IntegerCell(room.getCapacity());

        case EXAM_CAPACITY:
            if (room.getExamCapacity() == null)
                return null;
            return new IntegerCell(room.getExamCapacity());

        case AREA:
            if (room.getArea() == null)
                return null;
            return new RoomAreaCell(room.getArea());

        case COORDINATES:
            if (!room.hasCoordinates())
                return null;
            return new Label(MESSAGES.coordinates(room.getX(), room.getY()));

        case DISTANCE_CHECK:
            Image dc = new Image(!room.isIgnoreTooFar() ? RESOURCES.on() : RESOURCES.off());
            dc.setTitle(!room.isIgnoreTooFar() ? MESSAGES.infoDistanceCheckOn() : MESSAGES.infoDistanceCheckOff());
            return dc;

        case ROOM_CHECK:
            Image rc = new Image(!room.isIgnoreRoomCheck() ? RESOURCES.on() : RESOURCES.off());
            rc.setTitle(!room.isIgnoreRoomCheck() ? MESSAGES.infoRoomCheckOn() : MESSAGES.infoRoomCheckOff());
            return rc;

        case PREFERENCE:
            if (iDepartment != null) {
                for (DepartmentInterface department : room.getDepartments()) {
                    if (iDepartment.equals(department.getDeptCode()) && department.getPreference() != null) {
                        return new PreferenceCell(department);
                    }
                }
                return null;
            } else {
                boolean hasPreferences = false;
                for (DepartmentInterface department : room.getDepartments())
                    if (department.getPreference() != null) {
                        hasPreferences = true;
                        break;
                    }
                if (hasPreferences)
                    return new PreferenceCell(room.getDepartments());
                else
                    return null;
            }

        case MAP:
            if (!room.hasMiniMapUrl())
                return null;
            return new MapCell(room);

        case PICTURES:
            if (idx == 0) {
                return (room.hasPictures(null) ? new PicturesCell(room, null) : null);
            } else {
                AttachmentTypeInterface type = iProperties.getTableTypes().get(idx - 1);
                return (room.hasPictures(type) ? new PicturesCell(room, type) : null);
            }

        case AVAILABILITY:
            if (room.getAvailability() == null)
                return null;
            return new AvailabilityCell(room, false);

        case DEPARTMENTS:
            return new DepartmentCell(true, room.getDepartments(), room.getControlDepartment(),
                    isAllDepartments(room));

        case CONTROL_DEPT:
            return new DepartmentCell(true, room.getControlDepartment());

        case EXAM_TYPES:
            return new ExamTypesCell(room.getUniqueId(), room.getExamTypes());

        case PERIOD_PREF:
            if (room.getPeriodPreference() == null)
                return null;
            if (iDepartment != null && room.hasExamTypes())
                for (ExamTypeInterface type : room.getExamTypes())
                    if (iDepartment.equals(type.getReference()))
                        return new PeriodPreferenceCell(room, type);
            return null;

        case EVENT_DEPARTMENT:
            if (room.getEventDepartment() == null)
                return null;
            final DepartmentCell edc = new DepartmentCell(false, room.getEventDepartment());
            if (room.isCanSeeEventAvailability()) {
                edc.addMouseOverHandler(new MouseOverHandler() {
                    @Override
                    public void onMouseOver(MouseOverEvent event) {
                        RoomSharingHint.showHint(edc.getElement(), room.getUniqueId(), true);
                    }
                });
                edc.addMouseOutHandler(new MouseOutHandler() {
                    @Override
                    public void onMouseOut(MouseOutEvent event) {
                        RoomSharingHint.hideHint();
                    }
                });
            }
            return edc;

        case EVENT_STATUS:
            if (room.getEventStatus() != null || room.getDefaultEventStatus() != null)
                return new StatusCell(room.getEventStatus(), room.getDefaultEventStatus());
            else
                return null;

        case EVENT_AVAILABILITY:
            if (room.getEventAvailability() == null)
                return null;
            return new AvailabilityCell(room, true);

        case EVENT_MESSAGE:
            if (room.hasEventNote() || room.hasDefaultEventNote())
                return new NoteCell(room.getEventNote(), room.getDefaultEventNote());
            else
                return null;

        case BREAK_TIME:
            if (room.getBreakTime() != null || room.getDefaultBreakTime() != null)
                return new BreakTimeCell(room.getBreakTime(), room.getDefaultBreakTime());
            else
                return null;

        case GROUPS:
            if (room.getGroups().isEmpty())
                return null;
            return new GroupsCell(room.getGroups());

        case FEATURES:
            if (idx == 0) {
                List<FeatureInterface> features = room.getFeatures((Long) null);
                if (features.isEmpty())
                    return null;
                return new FeaturesCell(features);
            } else {
                FeatureTypeInterface type = getFeatureType(idx - 1);
                List<FeatureInterface> featuresOfType = room.getFeatures(type);
                if (featuresOfType.isEmpty())
                    return null;
                return new FeaturesCell(featuresOfType);
            }
        }
        return null;
    }

    public int addRoom(final RoomDetailInterface room) {
        List<Widget> widgets = new ArrayList<Widget>();

        for (RoomsColumn column : RoomsColumn.values()) {
            int nbrCells = getNbrCells(column);
            for (int idx = 0; idx < nbrCells; idx++) {
                Widget cell = getCell(room, column, idx);
                if (cell == null) {
                    cell = new P();
                } else if (hasShowHideOperation(column)) {
                    show(column, idx);
                }
                widgets.add(cell);
            }
        }

        int row = addRow(room, widgets);
        getRowFormatter().setStyleName(row, "row");
        for (int col = 0; col < getCellCount(row); col++)
            getCellFormatter().setStyleName(row, col, "cell");

        if (!isVisible())
            setVisible(true);

        return row;
    }

    protected void resetVisibility() {
        for (RoomsColumn column : RoomsColumn.values()) {
            int nrCells = getNbrCells(column);
            int cellIdx = getCellIndex(column);
            for (int idx = 0; idx < nrCells; idx++) {
                final int colIdx = cellIdx + idx;
                setColumnVisible(colIdx, !hasShowHideOperation(column));
            }
        }
    }

    protected void show(RoomsColumn column, int idx) {
        int colIdx = getCellIndex(column) + idx;
        if (RoomCookie.getInstance().get(iMode, colIdx) && !isColumnVisible(colIdx))
            setColumnVisible(colIdx, true);
        int flag = (1 << colIdx);
        if ((iFlags & flag) == 0)
            iFlags += flag;
    }

    @Override
    public void clearTable(int headerRows) {
        super.clearTable(headerRows);
        resetVisibility();
        iFlags = 0;
        setVisible(false);
    }

    public int getFlags() {
        return iFlags;
    }

    public boolean isVisible(RoomsColumn column) {
        return isColumnVisible(getCellIndex(column));
    }

    public static class IntegerCell extends Label
            implements UniTimeTable.HasCellAlignment, UniTimeTable.HasColSpan, TakesValue<Integer> {

        public IntegerCell(Integer value) {
            super();
            setValue(value);
        }

        @Override
        public void setValue(Integer value) {
            setText(value == null ? "" : value.toString());
        }

        @Override
        public Integer getValue() {
            return getText().isEmpty() ? null : new Integer(getText());
        }

        @Override
        public HorizontalAlignmentConstant getCellAlignment() {
            return HasHorizontalAlignment.ALIGN_RIGHT;
        }

        @Override
        public int getColSpan() {
            return 1;
        }
    }

    class RoomNameCell extends Label {
        RoomNameCell(final RoomDetailInterface room) {
            super(room.hasDisplayName() ? MESSAGES.label(room.getLabel(), room.getDisplayName()) : room.getLabel(),
                    room.hasDisplayName());
            addMouseOverHandler(new MouseOverHandler() {
                @Override
                public void onMouseOver(MouseOverEvent event) {
                    RoomHint.showHint(RoomNameCell.this.getElement(), room.getUniqueId(), room.getPrefix(),
                            room.getProperty("distance", null), true);
                }
            });
            addMouseOutHandler(new MouseOutHandler() {
                @Override
                public void onMouseOut(MouseOutEvent event) {
                    RoomHint.hideHint();
                }
            });
            if (iDepartment != null && iProperties != null && iProperties.isCanSeeCourses()) {
                for (DepartmentInterface d : room.getDepartments()) {
                    if (iDepartment.equals(d.getDeptCode()) && d.getPreference() != null) {
                        getElement().getStyle().setColor(d.getPreference().getColor());
                        room.setPrefix(d.getPreference().getName());
                    }
                }
            }
        }
    }

    class SelectableRoomNameCell extends AriaCheckBox {
        SelectableRoomNameCell(final RoomDetailInterface room) {
            addClickHandler(new ClickHandler() {
                @Override
                public void onClick(ClickEvent event) {
                    event.stopPropagation();
                }
            });
            addValueChangeHandler(new ValueChangeHandler<Boolean>() {
                @Override
                public void onValueChange(ValueChangeEvent<Boolean> event) {
                    setSelected(getRow(room), event.getValue());
                }
            });
            setText(room.hasDisplayName() ? MESSAGES.label(room.getLabel(), room.getDisplayName())
                    : room.getLabel());
            setWordWrap(room.hasDisplayName());
            addMouseOverHandler(new MouseOverHandler() {
                @Override
                public void onMouseOver(MouseOverEvent event) {
                    RoomHint.showHint(SelectableRoomNameCell.this.getElement(), room.getUniqueId(),
                            room.getPrefix(), room.getProperty("distance", null), true);
                }
            });
            addMouseOutHandler(new MouseOutHandler() {
                @Override
                public void onMouseOut(MouseOutEvent event) {
                    RoomHint.hideHint();
                }
            });
            if (iDepartment != null && iProperties != null && iProperties.isCanSeeCourses()) {
                for (DepartmentInterface d : room.getDepartments()) {
                    if (iDepartment.equals(d.getDeptCode()) && d.getPreference() != null) {
                        getElement().getStyle().setColor(d.getPreference().getColor());
                        room.setPrefix(d.getPreference().getName());
                    }
                }
            }
        }
    }

    public static class RoomAreaCell extends HTML implements UniTimeTable.HasCellAlignment {
        public RoomAreaCell(Double value) {
            super(value == null ? "" : MESSAGES.roomArea(value));
        }

        @Override
        public HorizontalAlignmentConstant getCellAlignment() {
            return HasHorizontalAlignment.ALIGN_RIGHT;
        }
    }

    public static class FeaturesCell extends P implements HasRefresh {
        Map<FeatureInterface, P> iFeatures = new HashMap<FeatureInterface, P>();

        public FeaturesCell(List<? extends FeatureInterface> features) {
            super();
            setStyleName("features");
            for (FeatureInterface feature : features) {
                P p = new P("feature");
                p.setText(feature.getLabel());
                if (feature.getTitle() != null)
                    p.setTitle(feature.getTitle());
                if (feature.getDepartment() != null) {
                    p.setText(feature.getLabel() + " (" + RoomsTable.toString(feature.getDepartment(), true) + ")");
                    if (feature.getDepartment().getColor() != null)
                        p.getElement().getStyle().setColor(feature.getDepartment().getColor());
                }
                iFeatures.put(feature, p);
                add(p);
            }
        }

        @Override
        public void refresh() {
            for (Map.Entry<FeatureInterface, P> e : iFeatures.entrySet()) {
                P p = e.getValue();
                FeatureInterface feature = e.getKey();
                if (feature.getDepartment() != null)
                    p.setText(feature.getLabel() + " (" + RoomsTable.toString(feature.getDepartment(), true) + ")");
            }
        }
    }

    public static class GroupsCell extends P implements HasRefresh {
        Map<GroupInterface, P> iGroups = new HashMap<GroupInterface, P>();

        public GroupsCell(List<? extends GroupInterface> groups) {
            super();
            setStyleName("groups");
            for (GroupInterface group : groups) {
                P p = new P("group");
                p.setText(group.getLabel());
                if (group.getTitle() != null)
                    p.setTitle(group.getTitle());
                if (group.getDepartment() != null) {
                    p.setText(group.getLabel() + " (" + RoomsTable.toString(group.getDepartment(), true) + ")");
                    if (group.getDepartment().getColor() != null)
                        p.getElement().getStyle().setColor(group.getDepartment().getColor());
                }
                iGroups.put(group, p);
                add(p);
            }
        }

        @Override
        public void refresh() {
            for (Map.Entry<GroupInterface, P> e : iGroups.entrySet()) {
                P p = e.getValue();
                GroupInterface group = e.getKey();
                if (group.getDepartment() != null)
                    p.setText(group.getLabel() + " (" + RoomsTable.toString(group.getDepartment(), true) + ")");
            }
        }
    }

    public static class NoteCell extends P {
        public NoteCell(String note, String defaultNote) {
            super("note");
            if (note != null) {
                setHTML(note.replace("\\n", "<br>"));
                setTitle(note);
            } else if (defaultNote != null) {
                addStyleName("default");
                setHTML(defaultNote.replace("\\n", "<br>"));
                setTitle(defaultNote);
            }
        }
    }

    public static class StatusCell extends P {
        public StatusCell(Integer status, Integer defaultStatus) {
            super("status");
            if (status != null) {
                setHTML(CONSTANTS.eventStatusAbbv()[status]);
                setTitle(CONSTANTS.eventStatusName()[status]);
            } else if (defaultStatus != null) {
                addStyleName("default");
                setText(CONSTANTS.eventStatusAbbv()[defaultStatus]);
                setTitle(CONSTANTS.eventStatusName()[defaultStatus]);
            } else {
                setHTML(CONSTANTS.eventStatusAbbv()[0]);
                setTitle(CONSTANTS.eventStatusName()[0]);
            }
        }
    }

    public static class BreakTimeCell extends P {
        public BreakTimeCell(Integer breakTime, Integer defaultBreakTime) {
            super("break");
            if (breakTime != null) {
                if (breakTime != 0)
                    setText(breakTime.toString());
            } else if (defaultBreakTime != null) {
                addStyleName("default");
                if (defaultBreakTime != 0)
                    setText(defaultBreakTime.toString());
            }
        }
    }

    public static String toString(DepartmentInterface d, boolean ext) {
        RoomCookie cookie = RoomCookie.getInstance();
        switch (DeptMode.values()[cookie.getDeptMode()]) {
        case ABBV:
            return ext ? d.getExtAbbreviationWhenExist() : d.getAbbreviationOrCode();
        case CODE:
            return d.getDeptCode();
        case ABBV_NAME:
            return ext ? d.getExtAbbreviationWhenExist() + " - " + d.getExtLabelWhenExist()
                    : d.getAbbreviationOrCode() + " - " + d.getLabel();
        case CODE_NAME:
            return ext ? d.getDeptCode() + " - " + d.getExtLabelWhenExist()
                    : d.getDeptCode() + " - " + d.getLabel();
        case NAME:
            return ext ? d.getExtLabelWhenExist() : d.getLabel();
        default:
            return d.getDeptCode();
        }
    }

    public static class DepartmentCell extends P implements HasRefresh {
        boolean iExt;
        Map<DepartmentInterface, P> iP = new HashMap<DepartmentInterface, P>();

        public DepartmentCell(boolean ext, DepartmentInterface... departments) {
            super("departments");
            iExt = ext;
            for (DepartmentInterface department : departments) {
                if (department == null)
                    continue;
                P p = new P("department");
                p.setText(RoomsTable.toString(department, iExt));
                if (department.getTitle() != null)
                    p.setTitle(department.getTitle());
                if (department.getColor() != null)
                    p.getElement().getStyle().setColor(department.getColor());
                add(p);
                iP.put(department, p);
            }
        }

        public DepartmentCell(boolean ext, List<DepartmentInterface> departments, DepartmentInterface control,
                boolean all) {
            super("departments");
            iExt = ext;
            if (all) {
                P p = new P("department", "all");
                p.setText(MESSAGES.departmentsAllLabel());
                p.setTitle(MESSAGES.departmentsAllTitle());
                add(p);
            } else {
                for (DepartmentInterface department : departments) {
                    P p = new P("department");
                    p.setText(RoomsTable.toString(department, iExt));
                    if (department.getTitle() != null)
                        p.setTitle(department.getTitle());
                    if (department.getColor() != null)
                        p.getElement().getStyle().setColor(department.getColor());
                    if (department.equals(control))
                        p.addStyleName("control");
                    iP.put(department, p);
                    add(p);
                }
            }
        }

        @Override
        public void refresh() {
            for (Map.Entry<DepartmentInterface, P> e : iP.entrySet())
                e.getValue().setText(RoomsTable.toString(e.getKey(), iExt));
        }
    }

    public static class PreferenceCell extends DepartmentCell {
        public PreferenceCell(List<DepartmentInterface> departments) {
            super(true);
            boolean abbv = RoomCookie.getInstance().getDeptMode() <= 1;
            for (DepartmentInterface department : departments) {
                if (department.getPreference() == null)
                    continue;
                P p = new P("department");
                if (abbv) {
                    String prefAbbv = department.getPreference().getAbbv();
                    p.setText(MESSAGES.roomPreferenceShort(RoomsTable.toString(department, iExt),
                            prefAbbv == null ? department.getPreference().getName() : prefAbbv));
                } else {
                    p.setText(MESSAGES.roomPreference(RoomsTable.toString(department, iExt),
                            department.getPreference().getName()));
                }
                p.setTitle(department.getPreference().getName() + " " + department.getLabel());
                p.getElement().getStyle().setColor(department.getPreference().getColor());
                iP.put(department, p);
                add(p);
            }
        }

        public PreferenceCell(DepartmentInterface department) {
            super(true);
            setText(department.getPreference().getName());
            setTitle(department.getPreference().getName() + " " + department.getLabel());
            getElement().getStyle().setColor(department.getPreference().getColor());
        }

        @Override
        public void refresh() {
            boolean abbv = RoomCookie.getInstance().getDeptMode() <= 1;
            for (Map.Entry<DepartmentInterface, P> e : iP.entrySet()) {
                DepartmentInterface department = e.getKey();
                if (abbv) {
                    String prefAbbv = department.getPreference().getAbbv();
                    e.getValue().setText(MESSAGES.roomPreferenceShort(RoomsTable.toString(department, iExt),
                            prefAbbv == null ? department.getPreference().getName() : prefAbbv));
                } else {
                    e.getValue().setText(MESSAGES.roomPreference(RoomsTable.toString(department, iExt),
                            department.getPreference().getName()));
                }
            }
        }

    }

    public static class ExamTypesCell extends P {
        public ExamTypesCell(final Long roomId, List<ExamTypeInterface> examTypes) {
            super("exam-types");
            for (final ExamTypeInterface examType : examTypes) {
                final P p = new P(examType.isFinal() ? "final" : "midterm");
                p.setText(examType.getLabel());
                p.addMouseOverHandler(new MouseOverHandler() {
                    @Override
                    public void onMouseOver(MouseOverEvent event) {
                        PeriodPreferencesHint.showHint(p.getElement(), roomId, examType.getId());
                    }
                });
                p.addMouseOutHandler(new MouseOutHandler() {
                    @Override
                    public void onMouseOut(MouseOutEvent event) {
                        PeriodPreferencesHint.hideHint();
                    }
                });
                add(p);
            }
        }
    }

    public static class RoomCell extends Label {
        public RoomCell(RoomPropertyInterface property) {
            super(property == null ? "" : property.getLabel());
            if (property != null) {
                if (property.getTitle() != null)
                    setTitle(property.getTitle());
                if (property.getColor() != null)
                    getElement().getStyle().setColor(property.getColor());
            }
        }
    }

    public static class PictureCell extends Image {
        public PictureCell(RoomPictureInterface picture) {
            super();
            setStyleName("picture");
            setUrl(GWT.getHostPageBaseURL() + "picture?id=" + picture.getUniqueId());
            setTitle(picture.getName()
                    + (picture.getPictureType() == null ? "" : " (" + picture.getPictureType().getLabel() + ")"));
            setAltText(picture.getName() + (picture.getPictureType() == null ? ""
                    : " (" + picture.getPictureType().getAbbreviation() + ")"));
        }
    }

    public static class LinkCell extends ImageLink {
        LinkCell(RoomPictureInterface picture) {
            super(new Image(RESOURCES.download()),
                    GWT.getHostPageBaseURL() + "picture?id=" + picture.getUniqueId());
            setStyleName("link");
            setTitle(picture.getName()
                    + (picture.getPictureType() == null ? "" : " (" + picture.getPictureType().getLabel() + ")"));
            setText(picture.getName() + (picture.getPictureType() == null ? ""
                    : " (" + picture.getPictureType().getAbbreviation() + ")"));
            setTarget("_blank");
            sinkEvents(Event.ONCLICK);
        }

        @Override
        public void onBrowserEvent(Event event) {
            if (event.getTypeInt() == Event.ONCLICK) {
                event.stopPropagation();
            }
            super.onBrowserEvent(event);
        }
    }

    public static class PicturesCell extends P {
        public PicturesCell(RoomDetailInterface room) {
            super("pictures");
            if (room.hasTablePictures()) {
                for (RoomPictureInterface picture : room.getTablePictures())
                    add(picture.getPictureType() == null || picture.getPictureType().isImage()
                            ? new PictureCell(picture)
                            : new LinkCell(picture));
            }
        }

        public PicturesCell(RoomDetailInterface room, AttachmentTypeInterface type) {
            super("pictures");
            if (room.hasPictures(type)) {
                for (RoomPictureInterface picture : room.getPictures(type))
                    add(picture.getPictureType() == null || picture.getPictureType().isImage()
                            ? new PictureCell(picture)
                            : new LinkCell(picture));
            }
        }
    }

    public static class MapCell extends Image {
        public MapCell(RoomDetailInterface room) {
            super();
            if (room.hasMiniMapUrl()) {
                setStyleName("map");
                setUrl(room.getMiniMapUrl());
                setTitle(MESSAGES.titleRoomMap(room.getLabel()));
            }
        }
    }

    public static class AvailabilityCell extends P implements HasRefresh {
        private boolean iEvents;
        private RoomDetailInterface iRoom;

        public AvailabilityCell(RoomDetailInterface room, boolean events) {
            super("availability");
            iRoom = room;
            iEvents = events;
            addMouseOverHandler(new MouseOverHandler() {
                @Override
                public void onMouseOver(MouseOverEvent event) {
                    RoomSharingHint.showHint(getElement(), iRoom.getUniqueId(), iEvents);
                }
            });
            addMouseOutHandler(new MouseOutHandler() {
                @Override
                public void onMouseOut(MouseOutEvent event) {
                    RoomSharingHint.hideHint();
                }
            });
            refresh();
        }

        @Override
        public void refresh() {
            clear();
            setHTML("");
            RoomCookie cookie = RoomCookie.getInstance();
            if (iEvents) {
                if (cookie.isGridAsText()) {
                    if (iRoom.getEventAvailability() != null) {
                        P p = new P("text");
                        p.setHTML(iRoom.getEventAvailability());
                        add(p);
                    }
                } else {
                    Image availability = new Image(GWT.getHostPageBaseURL() + "pattern?loc=" + iRoom.getUniqueId()
                            + "&e=1&v=" + (cookie.areRoomsHorizontal() ? "0" : "1")
                            + (cookie.hasMode() ? "&s=" + cookie.getMode() : ""));
                    availability.setStyleName("grid");
                    add(availability);
                }
            } else {
                if (cookie.isGridAsText()) {
                    if (iRoom.getAvailability() != null && !iRoom.getAvailability().isEmpty()) {
                        P p = new P("text");
                        p.setHTML(iRoom.getAvailability());
                        add(p);
                    }
                } else {
                    Image availability = new Image(GWT.getHostPageBaseURL() + "pattern?loc=" + iRoom.getUniqueId()
                            + "&v=" + (cookie.areRoomsHorizontal() ? "0" : "1")
                            + (cookie.hasMode() ? "&s=" + cookie.getMode() : ""));
                    availability.setStyleName("grid");
                    add(availability);
                }
                if (iRoom.getRoomSharingNote() != null && !iRoom.getRoomSharingNote().isEmpty()) {
                    P p = new P("note");
                    p.setHTML(iRoom.getRoomSharingNote());
                    p.setTitle(iRoom.getRoomSharingNote());
                    add(p);
                }
            }
        }
    }

    public static class PeriodPreferenceCell extends P implements HasRefresh {
        private RoomDetailInterface iRoom;
        private ExamTypeInterface iType;

        public PeriodPreferenceCell(RoomDetailInterface room, ExamTypeInterface type) {
            super("periodpref");
            iRoom = room;
            iType = type;
            addMouseOverHandler(new MouseOverHandler() {
                @Override
                public void onMouseOver(MouseOverEvent event) {
                    PeriodPreferencesHint.showHint(getElement(), iRoom.getUniqueId(), iType.getId());
                }
            });
            addMouseOutHandler(new MouseOutHandler() {
                @Override
                public void onMouseOut(MouseOutEvent event) {
                    RoomSharingHint.hideHint();
                }
            });
            refresh();
        }

        @Override
        public void refresh() {
            clear();
            setHTML("");
            RoomCookie cookie = RoomCookie.getInstance();
            if (cookie.isGridAsText() || !iType.isFinal()) {
                if (iRoom.getPeriodPreference() != null)
                    setHTML(iRoom.getPeriodPreference());
            } else {
                add(new Image(GWT.getHostPageBaseURL() + "pattern?loc=" + iRoom.getUniqueId() + "&xt="
                        + iType.getId() + "&v=" + (cookie.areRoomsHorizontal() ? "0" : "1")
                        + (cookie.hasMode() ? "&s=" + cookie.getMode() : "")));
            }
        }
    }

    public interface Check {
        public boolean isChecked();
    }

    public static enum DeptMode {
        CODE(MESSAGES.fieldCode()), ABBV(MESSAGES.fieldAbbreviation()), NAME(MESSAGES.fieldName()), ABBV_NAME(
                MESSAGES.fieldAbbv() + " - " + MESSAGES.fieldName()), CODE_NAME(
                        MESSAGES.fieldCode() + " - " + MESSAGES.fieldName());

        private String iName;

        DeptMode(String name) {
            iName = name;
        }

        public String getName() {
            return iName;
        }
    }

    public static interface SortOperation extends Operation, HasColumnName {
    }

    public static interface HasRefresh {
        public void refresh();
    }

    public RoomDetailInterface getRoom(Long roomId) {
        if (roomId == null)
            return null;
        for (int i = 1; i < getRowCount(); i++) {
            if (roomId.equals(getData(i).getUniqueId()))
                return getData(i);
        }
        return null;
    }

    public void scrollTo(Long roomId) {
        if (roomId == null)
            return;
        for (int i = 1; i < getRowCount(); i++) {
            if (roomId.equals(getData(i).getUniqueId())) {
                ToolBox.scrollToElement(getRowFormatter().getElement(i));
            }
        }
    }

    public RoomDetailInterface getPrevious(Long roomId) {
        if (roomId == null)
            return null;
        for (int i = 2; i < getRowCount(); i++) {
            if (roomId.equals(getData(i).getUniqueId()))
                return getData(i - 1);
        }
        return null;
    }

    public RoomDetailInterface getNext(Long roomId) {
        if (roomId == null)
            return null;
        for (int i = 1; i < getRowCount() - 1; i++) {
            if (roomId.equals(getData(i).getUniqueId()))
                return getData(i + 1);
        }
        return null;
    }

    public Boolean isRoomSelected(int row) {
        Widget w = getWidget(row, 0);
        if (w != null && w instanceof CheckBox) {
            return ((CheckBox) w).getValue();
        } else {
            return null;
        }
    }

    public boolean isRoomSelected(RoomDetailInterface room) {
        if (!iSelectable)
            return false;
        for (int row = 1; row < getRowCount(); row++) {
            if (getData(row).getUniqueId().equals(room.getUniqueId()))
                return isRoomSelected(row);
        }
        return false;
    }

    public int getRow(RoomDetailInterface room) {
        for (int row = 1; row < getRowCount(); row++)
            if (getData(row).getUniqueId().equals(room.getUniqueId()))
                return row;
        return -1;
    }

    public void selectRoom(RoomDetailInterface room, boolean value) {
        if (!iSelectable)
            return;
        for (int row = 1; row < getRowCount(); row++) {
            if (getData(row).getUniqueId().equals(room.getUniqueId())) {
                selectRoom(row, value);
                break;
            }
        }
    }

    public void selectRoom(int row, boolean value) {
        Widget w = getWidget(row, 0);
        if (w != null && w instanceof CheckBox) {
            ((CheckBox) w).setValue(value);
        }
    }

    public CheckBox getRoomSelection(int row) {
        Widget w = getWidget(row, 0);
        if (w != null && w instanceof CheckBox) {
            return (CheckBox) w;
        } else {
            return null;
        }
    }

    public boolean isAllDepartments(RoomDetailInterface room) {
        return room.getDepartments().size() > 3 && iProperties.getNrDepartments() == room.getDepartments().size();
    }
}