text:
package com.vaadin.tests.widgetset.client.v7.grid;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.logging.Logger;

import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
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.ContextMenuEvent;
import com.google.gwt.event.dom.client.ContextMenuHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.MenuItemSeparator;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.data.DataSource;
import com.vaadin.client.data.DataSource.RowHandle;
import com.vaadin.client.ui.VLabel;
import com.vaadin.tests.widgetset.client.v7.grid.GridBasicClientFeaturesWidget.Data;
import com.vaadin.v7.client.renderers.DateRenderer;
import com.vaadin.v7.client.renderers.HtmlRenderer;
import com.vaadin.v7.client.renderers.NumberRenderer;
import com.vaadin.v7.client.renderers.Renderer;
import com.vaadin.v7.client.renderers.TextRenderer;
import com.vaadin.v7.client.widget.grid.CellReference;
import com.vaadin.v7.client.widget.grid.CellStyleGenerator;
import com.vaadin.v7.client.widget.grid.DetailsGenerator;
import com.vaadin.v7.client.widget.grid.EditorHandler;
import com.vaadin.v7.client.widget.grid.EventCellReference;
import com.vaadin.v7.client.widget.grid.RendererCellReference;
import com.vaadin.v7.client.widget.grid.RowReference;
import com.vaadin.v7.client.widget.grid.RowStyleGenerator;
import com.vaadin.v7.client.widget.grid.datasources.ListDataSource;
import com.vaadin.v7.client.widget.grid.datasources.ListSorter;
import com.vaadin.v7.client.widget.grid.events.BodyKeyDownHandler;
import com.vaadin.v7.client.widget.grid.events.BodyKeyPressHandler;
import com.vaadin.v7.client.widget.grid.events.BodyKeyUpHandler;
import com.vaadin.v7.client.widget.grid.events.ColumnReorderEvent;
import com.vaadin.v7.client.widget.grid.events.ColumnReorderHandler;
import com.vaadin.v7.client.widget.grid.events.ColumnVisibilityChangeEvent;
import com.vaadin.v7.client.widget.grid.events.ColumnVisibilityChangeHandler;
import com.vaadin.v7.client.widget.grid.events.FooterKeyDownHandler;
import com.vaadin.v7.client.widget.grid.events.FooterKeyPressHandler;
import com.vaadin.v7.client.widget.grid.events.FooterKeyUpHandler;
import com.vaadin.v7.client.widget.grid.events.GridKeyDownEvent;
import com.vaadin.v7.client.widget.grid.events.GridKeyPressEvent;
import com.vaadin.v7.client.widget.grid.events.GridKeyUpEvent;
import com.vaadin.v7.client.widget.grid.events.HeaderKeyDownHandler;
import com.vaadin.v7.client.widget.grid.events.HeaderKeyPressHandler;
import com.vaadin.v7.client.widget.grid.events.HeaderKeyUpHandler;
import com.vaadin.v7.client.widget.grid.events.ScrollEvent;
import com.vaadin.v7.client.widget.grid.events.ScrollHandler;
import com.vaadin.v7.client.widget.grid.selection.SelectionModel;
import com.vaadin.v7.client.widget.grid.selection.SelectionModel.None;
import com.vaadin.v7.client.widgets.Grid;
import com.vaadin.v7.client.widgets.Grid.Column;
import com.vaadin.v7.client.widgets.Grid.FooterRow;
import com.vaadin.v7.client.widgets.Grid.HeaderRow;
import com.vaadin.v7.client.widgets.Grid.SelectionMode;
import com.vaadin.v7.shared.ui.grid.ScrollDestination;

/**
 * Grid basic client features test application.
 *
 * @since
 * @author Vaadin Ltd
 */
public class GridBasicClientFeaturesWidget
        extends PureGWTTestApplication<Grid<List<Data>>> {
    public static final String ROW_STYLE_GENERATOR_NONE = "None";
    public static final String ROW_STYLE_GENERATOR_ROW_INDEX = "Row numbers";
    public static final String ROW_STYLE_GENERATOR_EVERY_THIRD = "Every third";

    public static final String CELL_STYLE_GENERATOR_NONE = "None";
    public static final String CELL_STYLE_GENERATOR_SIMPLE = "Simple";
    public static final String CELL_STYLE_GENERATOR_COL_INDEX = "Column index";

    public static enum Renderers {
        TEXT_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER;
    }

    private class TestEditorHandler implements EditorHandler<List<Data>> {

        private Map<Grid.Column<?, ?>, TextBox> widgets = new HashMap<>();

        private Label log = new Label();

        {
            log.addStyleName("grid-editor-log");
            addSouth(log, 20);
        }

        @Override
        public void bind(EditorRequest<List<Data>> request) {
            List<Data> rowData = ds.getRow(request.getRowIndex());

            boolean hasSelectionColumn = !(grid
                    .getSelectionModel() instanceof None);
            for (int i = 0; i < rowData.size(); i++) {
                int columnIndex = hasSelectionColumn ? i + 1 : i;
                getWidget(columnIndex).setText(rowData.get(i).value.toString());
            }
            request.success();
        }

        @Override
        public void cancel(EditorRequest<List<Data>> request) {
            log.setText("Row " + request.getRowIndex() + " edit cancelled");
        }

        @Override
        public void save(EditorRequest<List<Data>> request) {
            if (secondEditorError) {
                request.failure(
                        "Syntethic fail of editor in column 2. "
                                + "This message is so long that it doesn't fit into its box",
                        Collections.<Column<?, List<Data>>> singleton(
                                grid.getColumn(2)));
                return;
            }
            try {
                log.setText("Row " + request.getRowIndex() + " edit committed");
                List<Data> rowData = ds.getRow(request.getRowIndex());

                int i = 0;
                for (; i < COLUMNS - MANUALLY_FORMATTED_COLUMNS; i++) {
                    rowData.get(i).value = getWidget(i).getText();
                }

                rowData.get(i).value = Integer
                        .valueOf(getWidget(i++).getText());
                rowData.get(i).value = new Date(getWidget(i++).getText());
                rowData.get(i).value = getWidget(i++).getText();
                rowData.get(i).value = Integer
                        .valueOf(getWidget(i++).getText());
                rowData.get(i).value = Integer
                        .valueOf(getWidget(i++).getText());

                // notify data source of changes
                ds.asList().set(request.getRowIndex(), rowData);
                request.success();
            } catch (Exception e) {
                Logger.getLogger(getClass().getName()).warning(e.toString());
                request.failure(null, null);
            }
        }

        @Override
        public TextBox getWidget(Grid.Column<?, List<Data>> column) {
            if (grid.getColumns().indexOf(column) == 0
                    && !(grid.getSelectionModel() instanceof None)) {
                return null;
            }

            TextBox w = widgets.get(column);
            if (w == null) {
                w = new TextBox();
                w.getElement().getStyle().setMargin(0, Unit.PX);
                widgets.put(column, w);
            }
            return w;
        }

        private TextBox getWidget(int i) {
            return getWidget(grid.getColumn(i));
        }
    }

    private static final int MANUALLY_FORMATTED_COLUMNS = 5;
    public static final int COLUMNS = 12;
    public static final int ROWS = 1000;

    private final Grid<List<Data>> grid;
    private List<List<Data>> data;
    private final ListDataSource<List<Data>> ds;
    private final ListSorter<List<Data>> sorter;

    private boolean secondEditorError = false;

    /**
     * Our basic data object
     */
    public final static class Data {
        Object value;
    }

    /**
     * @since
     * @return
     */
    private List<List<Data>> createData(int rowCount) {
        List<List<Data>> dataList = new ArrayList<>();
        Random rand = new Random();
        rand.setSeed(13334);
        long timestamp = 0;
        for (int row = 0; row < rowCount; row++) {

            List<Data> datarow = createDataRow(COLUMNS);
            dataList.add(datarow);
            Data d;

            int col = 0;
            for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) {
                d = datarow.get(col);
                d.value = "(" + row + ", " + col + ")";
            }

            d = datarow.get(col++);
            d.value = Integer.valueOf(row);

            d = datarow.get(col++);
            d.value = new Date(timestamp);
            timestamp += 91250000; // a bit over a day, just to get
                                   // variation

            d = datarow.get(col++);
            d.value = "" + row + "";

            d = datarow.get(col++);
            d.value = Integer.valueOf(rand.nextInt());

            d = datarow.get(col++);
            d.value = Integer.valueOf(rand.nextInt(5));
        }

        return dataList;
    }

    /**
     * Convenience method for creating a list of Data objects to be used as a
     * Row in the data source
     *
     * @param cols
     *            number of columns (items) to include in the row
     * @return
     */
    private List<Data> createDataRow(int cols) {
        List<Data> list = new ArrayList<>(cols);
        for (int i = 0; i < cols; ++i) {
            list.add(new Data());
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public GridBasicClientFeaturesWidget() {
        super(new Grid<List<Data>>());

        // Initialize data source
        data = createData(ROWS);

        ds = new ListDataSource<>(data);
        grid = getTestedWidget();
        grid.getElement().setId("testComponent");
        grid.setDataSource(ds);
        grid.addSelectAllHandler(ds.getSelectAllHandler());
        grid.setSelectionMode(SelectionMode.NONE);
        grid.setEditorHandler(new TestEditorHandler());

        sorter = new ListSorter<>(grid);

        // Create a bunch of grid columns

        // Data source layout:
        // text (String) * (COLUMNS - MANUALLY_FORMATTED_COLUMNS + 1) |
        // rownumber (Integer) | some date (Date) | row number as HTML (String)
        // | random value (Integer)

        int col = 0;

        // Text times COLUMNS - MANUALLY_FORMATTED_COLUMNS
        for (col = 0; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) {

            final int c = col;

            Grid.Column<String, List<Data>> column = new Grid.Column<String, List<Data>>(
                    createRenderer(Renderers.TEXT_RENDERER)) {
                @Override
                public String getValue(List<Data> row) {
                    return (String) row.get(c).value;
                }
            };

            column.setWidth(50 + c * 25);
            column.setHeaderCaption("Header (0," + c + ")");

            grid.addColumn(column);
        }

        // Integer row number
        {
            final int c = col++;
            Grid.Column<Integer, List<Data>> column = new Grid.Column<Integer, List<Data>>(
                    createRenderer(Renderers.NUMBER_RENDERER)) {
                @Override
                public Integer getValue(List<Data> row) {
                    return (Integer) row.get(c).value;
                }
            };
            grid.addColumn(column);
            column.setHeaderCaption("Header (0," + c + ")");
        }

        // Some date
        {
            final int c = col++;
            Grid.Column<Date, List<Data>> column = new Grid.Column<Date, List<Data>>(
                    createRenderer(Renderers.DATE_RENDERER)) {
                @Override
                public Date getValue(List<Data> row) {
                    return (Date) row.get(c).value;
                }
            };
            grid.addColumn(column);
            column.setHeaderCaption("Header (0," + c + ")");
        }

        // Row number as a HTML string
        {
            final int c = col++;
            Grid.Column<String, List<Data>> column = new Grid.Column<String, List<Data>>(
                    createRenderer(Renderers.HTML_RENDERER)) {
                @Override
                public String getValue(List<Data> row) {
                    return (String) row.get(c).value;
                }
            };
            grid.addColumn(column);
            column.setHeaderCaption("Header (0," + c + ")");
        }

        // Random integer value
        {
            final int c = col++;
            Grid.Column<Integer, List<Data>> column = new Grid.Column<Integer, List<Data>>(
                    createRenderer(Renderers.NUMBER_RENDERER)) {
                @Override
                public Integer getValue(List<Data> row) {
                    return (Integer) row.get(c).value;
                }
            };
            grid.addColumn(column);
            column.setHeaderCaption("Header (0," + c + ")");
        }

        // Random integer value between 0 and 5
        {
            final int c = col++;
            Grid.Column<Integer, List<Data>> column = new Grid.Column<Integer, List<Data>>(
                    createRenderer(Renderers.NUMBER_RENDERER)) {
                @Override
                public Integer getValue(List<Data> row) {
                    return (Integer) row.get(c).value;
                }
            };
            grid.addColumn(column);
            column.setHeaderCaption("Header (0," + c + ")");
        }

        grid.getColumn(3).setEditable(false);

        HeaderRow row = grid.getDefaultHeaderRow();
        for (int i = 0; i < col; ++i) {
            String caption = "Header (0," + i + ")";
            Grid.Column<?, ?> column = grid.getColumn(i);
            // Lets use some different cell types
            if (i % 3 == 0) {
                // No-op
            } else if (i % 2 == 0) {
                row.getCell(column).setHtml("" + caption + "");
            } else {
                row.getCell(column).setWidget(new HTML(caption));
            }
        }
        ++headerCounter;

        //
        // Populate the menu
        //

        createStateMenu();
        createColumnsMenu();
        createHeaderMenu();
        createFooterMenu();
        createEditorMenu();
        createInternalsMenu();
        createDataSourceMenu();
        createDetailsMenu();
        createSidebarMenu();

        grid.getElement().getStyle().setZIndex(0);

        //
        // Composite wrapping for grid.
        //
        boolean isComposite = Window.Location.getParameter("composite") != null;
        if (isComposite) {
            addNorth(new Composite() {
                {
                    initWidget(grid);
                }
            }, 400);
        } else {
            addNorth(grid, 400);
        }

        createKeyHandlers();
    }

    private void createInternalsMenu() {
        String[] listenersPath = { "Component", "Internals", "Listeners" };
        final Label label = new Label();
        addSouth(label, 20);

        addMenuCommand("Add scroll listener", new ScheduledCommand() {
            private HandlerRegistration scrollHandler = null;

            @Override
            public void execute() {
                if (scrollHandler != null) {
                    return;
                }
                scrollHandler = grid.addScrollHandler(new ScrollHandler() {
                    @Override
                    public void onScroll(ScrollEvent event) {
                        @SuppressWarnings("hiding")
                        final Grid<?> grid = (Grid<?>) event.getSource();
                        label.setText("scrollTop: " + grid.getScrollTop()
                                + ", scrollLeft: " + grid.getScrollLeft());
                    }
                });
            }
        }, listenersPath);
        addMenuCommand("Add ColumnReorder listener", new ScheduledCommand() {
            private HandlerRegistration columnReorderHandler = null;

            @Override
            public void execute() {
                if (columnReorderHandler != null) {
                    return;
                }
                final Label columnOrderLabel = new Label();
                columnOrderLabel.getElement().setId("columnreorder");
                addLineEnd(columnOrderLabel, 300);
                columnReorderHandler = grid.addColumnReorderHandler(
                        new ColumnReorderHandler<List<Data>>() {

                            private int eventIndex = 0;

                            @Override
                            public void onColumnReorder(
                                    ColumnReorderEvent<List<Data>> event) {
                                columnOrderLabel.getElement().setAttribute(
                                        "columns", "" + (++eventIndex));
                            }
                        });
            }
        }, listenersPath);
        addMenuCommand("Add Column Visibility Change listener",
                new ScheduledCommand() {
                    private HandlerRegistration columnVisibilityHandler = null;

                    @Override
                    public void execute() {
                        if (columnVisibilityHandler != null) {
                            return;
                        }
                        final Label columnOrderLabel = new Label();
                        columnOrderLabel.getElement().setId("columnvisibility");
                        addLineEnd(columnOrderLabel, 250);
                        ColumnVisibilityChangeHandler handler = new ColumnVisibilityChangeHandler<List<Data>>() {

                            private int eventIndex = 0;

                            @Override
                            public void onVisibilityChange(
                                    ColumnVisibilityChangeEvent<List<Data>> event) {
                                columnOrderLabel.getElement().setAttribute(
                                        "counter", "" + (++eventIndex));
                                columnOrderLabel.getElement().setAttribute(
                                        "useroriginated", (Boolean.toString(
                                                event.isUserOriginated())));
                                columnOrderLabel.getElement().setAttribute(
                                        "ishidden",
                                        (Boolean.toString(event.isHidden())));
                                columnOrderLabel.getElement().setAttribute(
                                        "columnindex", "" + grid.getColumns()
                                                .indexOf(event.getColumn()));
                            }
                        };

                        columnVisibilityHandler = grid
                                .addColumnVisibilityChangeHandler(handler);
                    }
                }, listenersPath);
        addMenuCommand("Add context menu listener", new ScheduledCommand() {

            HandlerRegistration handler = null;
            ContextMenuHandler contextMenuHandler = new ContextMenuHandler() {

                @Override
                public void onContextMenu(ContextMenuEvent event) {
                    event.preventDefault();
                    final String location;
                    EventCellReference<?> cellRef = grid.getEventCell();
                    if (cellRef.isHeader()) {
                        location = "header";
                    } else if (cellRef.isBody()) {
                        location = "body";
                    } else if (cellRef.isFooter()) {
                        location = "footer";
                    } else {
                        location = "somewhere";
                    }

                    getLogger().info("Prevented opening a context menu in grid "
                            + location);
                }
            };

            @Override
            public void execute() {
                if (handler != null) {
                    grid.unsinkEvents(Event.ONCONTEXTMENU);
                    handler.removeHandler();
                } else {
                    grid.sinkEvents(Event.ONCONTEXTMENU);
                    handler = grid.addDomHandler(contextMenuHandler,
                            ContextMenuEvent.getType());
                }
            }

        }, listenersPath);
    }

    private void createStateMenu() {
        String[] selectionModePath = { "Component", "State", "Selection mode" };
        String[] primaryStyleNamePath = { "Component", "State",
                "Primary Stylename" };
        String[] rowStyleGeneratorNamePath = { "Component", "State",
                "Row style generator" };
        String[] cellStyleGeneratorNamePath = { "Component", "State",
                "Cell style generator" };

        addMenuCommand("multi", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setSelectionMode(SelectionMode.MULTI);
            }
        }, selectionModePath);

        addMenuCommand("single", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setSelectionMode(SelectionMode.SINGLE);
            }
        }, selectionModePath);

        addMenuCommand("single (no deselect)", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setSelectionMode(SelectionMode.SINGLE);
                ((SelectionModel.Single<?>) grid.getSelectionModel())
                        .setDeselectAllowed(false);
            }
        }, selectionModePath);

        addMenuCommand("none", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setSelectionMode(SelectionMode.NONE);
            }
        }, selectionModePath);

        addMenuCommand("v-grid", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setStylePrimaryName("v-grid");

            }
        }, primaryStyleNamePath);

        addMenuCommand("v-escalator", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setStylePrimaryName("v-escalator");

            }
        }, primaryStyleNamePath);

        addMenuCommand("v-custom-style", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setStylePrimaryName("v-custom-style");

            }
        }, primaryStyleNamePath);

        addMenuCommand("Edit and refresh Row 0", new ScheduledCommand() {
            @Override
            public void execute() {
                DataSource<List<Data>> ds = grid.getDataSource();
                RowHandle<List<Data>> rowHandle = ds.getHandle(ds.getRow(0));
                rowHandle.getRow().get(0).value = "Foo";
                rowHandle.updateRow();
            }
        }, "Component", "State");

        addMenuCommand("Delayed edit of Row 0", new ScheduledCommand() {
            @Override
            public void execute() {
                DataSource<List<Data>> ds = grid.getDataSource();
                final RowHandle<List<Data>> rowHandle = ds
                        .getHandle(ds.getRow(0));

                new Timer() {
                    @Override
                    public void run() {
                        rowHandle.getRow().get(0).value = "Bar";
                        rowHandle.updateRow();
                    }

                }.schedule(5000);
            }
        }, "Component", "State");

        addMenuCommand(ROW_STYLE_GENERATOR_NONE, new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setRowStyleGenerator(null);
            }
        }, rowStyleGeneratorNamePath);

        addMenuCommand(ROW_STYLE_GENERATOR_EVERY_THIRD, new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setRowStyleGenerator(new RowStyleGenerator<List<Data>>() {

                    @Override
                    public String getStyle(
                            RowReference<List<Data>> rowReference) {
                        if (rowReference.getRowIndex() % 3 == 0) {
                            return "third";
                        } else {
                            // First manual col is integer
                            Integer value = (Integer) rowReference.getRow().get(
                                    COLUMNS - MANUALLY_FORMATTED_COLUMNS).value;
                            return value.toString();
                        }
                    }
                });

            }
        }, rowStyleGeneratorNamePath);

        addMenuCommand(ROW_STYLE_GENERATOR_ROW_INDEX, new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setRowStyleGenerator(new RowStyleGenerator<List<Data>>() {

                    @Override
                    public String getStyle(
                            RowReference<List<Data>> rowReference) {
                        return Integer.toString(rowReference.getRowIndex());
                    }
                });

            }
        }, rowStyleGeneratorNamePath);

        addMenuCommand(CELL_STYLE_GENERATOR_NONE, new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setCellStyleGenerator(null);
            }
        }, cellStyleGeneratorNamePath);

        addMenuCommand(CELL_STYLE_GENERATOR_SIMPLE, new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setCellStyleGenerator(
                        new CellStyleGenerator<List<Data>>() {

                            @Override
                            public String getStyle(
                                    CellReference<List<Data>> cellReference) {
                                Grid.Column<?, List<Data>> column = cellReference
                                        .getColumn();
                                if (column == grid.getColumn(2)) {
                                    return "two";
                                } else if (column == grid.getColumn(
                                        COLUMNS - MANUALLY_FORMATTED_COLUMNS)) {
                                    // First manual col is integer
                                    Integer value = (Integer) column
                                            .getValue(cellReference.getRow());
                                    return value.toString();

                                } else {
                                    return null;
                                }
                            }
                        });
            }
        }, cellStyleGeneratorNamePath);
        addMenuCommand(CELL_STYLE_GENERATOR_COL_INDEX, new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setCellStyleGenerator(
                        new CellStyleGenerator<List<Data>>() {

                            @Override
                            public String getStyle(
                                    CellReference<List<Data>> cellReference) {
                                return cellReference.getRowIndex() + "_"
                                        + grid.getColumns().indexOf(
                                                cellReference.getColumn());
                            }
                        });
            }
        }, cellStyleGeneratorNamePath);

        for (int i = -1; i <= COLUMNS; i++) {
            final int index = i;
            // Including dummy "columns" prefix because TB fails to select item
            // if it's too narrow
            addMenuCommand(Integer.toString(index) + " columns",
                    new ScheduledCommand() {
                        @Override
                        public void execute() {
                            grid.setFrozenColumnCount(index);
                        }
                    }, "Component", "State", "Frozen column count");
        }

        addMenuCommand("Enabled", new ScheduledCommand() {

            @Override
            public void execute() {
                grid.setEnabled(!grid.isEnabled());
            }
        }, "Component", "State");
        addMenuCommand("Reverse grid columns", new ScheduledCommand() {

            @Override
            public void execute() {
                List<Column> columns = new ArrayList<>(grid.getColumns());
                Collections.reverse(columns);
                grid.setColumnOrder(
                        columns.toArray(new Column[columns.size()]));
            }
        }, "Component", "State");
        addMenuCommand("Column Reordering", new ScheduledCommand() {

            @Override
            public void execute() {
                grid.setColumnReorderingAllowed(
                        !grid.isColumnReorderingAllowed());
            }
        }, "Component", "State");
        addMenuCommand("250px", new ScheduledCommand() {

            @Override
            public void execute() {
                grid.setWidth("250px");
            }
        }, "Component", "State", "Width");
        addMenuCommand("500px", new ScheduledCommand() {

            @Override
            public void execute() {
                grid.setWidth("500px");
            }
        }, "Component", "State", "Width");
        addMenuCommand("750px", new ScheduledCommand() {

            @Override
            public void execute() {
                grid.setWidth("750px");
            }
        }, "Component", "State", "Width");
        addMenuCommand("1000px", new ScheduledCommand() {

            @Override
            public void execute() {
                grid.setWidth("1000px");
            }
        }, "Component", "State", "Width");

        createScrollToRowMenu();
    }

    private void createScrollToRowMenu() {
        String[] menupath = new String[] { "Component", "State", "Scroll to...",
                null };

        for (int i = 0; i < ROWS; i += 100) {
            menupath[3] = "Row " + i + "...";
            for (final ScrollDestination scrollDestination : ScrollDestination
                    .values()) {
                final int row = i;
                addMenuCommand("Destination " + scrollDestination,
                        new ScheduledCommand() {
                            @Override
                            public void execute() {
                                grid.scrollToRow(row, scrollDestination);
                            }
                        }, menupath);
            }
        }

        int i = ROWS - 1;
        menupath[3] = "Row " + i + "...";
        for (final ScrollDestination scrollDestination : ScrollDestination
                .values()) {
            final int row = i;
            addMenuCommand("Destination " + scrollDestination,
                    new ScheduledCommand() {
                        @Override
                        public void execute() {
                            grid.scrollToRow(row, scrollDestination);
                        }
                    }, menupath);
        }

    }

    private void createColumnsMenu() {

        for (int i = 0; i < COLUMNS; i++) {
            final int index = i;
            final Grid.Column<?, List<Data>> column = grid.getColumn(index);
            addMenuCommand("Sortable", new ScheduledCommand() {
                @Override
                public void execute() {
                    column.setSortable(!column.isSortable());
                }
            }, "Component", "Columns", "Column " + i);
            addMenuCommand("Hidden", new ScheduledCommand() {
                @Override
                public void execute() {
                    column.setHidden(!column.isHidden());
                }
            }, "Component", "Columns", "Column " + i);
            addMenuCommand("Hidable", new ScheduledCommand() {
                @Override
                public void execute() {
                    column.setHidable(!column.isHidable());
                }
            }, "Component", "Columns", "Column " + i);
            addMenuCommand("auto", new ScheduledCommand() {
                @Override
                public void execute() {
                    column.setWidth(-1);
                }
            }, "Component", "Columns", "Column " + i, "Width");
            addMenuCommand("50px", new ScheduledCommand() {
                @Override
                public void execute() {
                    column.setWidth(50);
                }
            }, "Component", "Columns", "Column " + i, "Width");
            addMenuCommand("200px", new ScheduledCommand() {
                @Override
                public void execute() {
                    column.setWidth(200);
                }
            }, "Component", "Columns", "Column " + i, "Width");

            // Header types
            addMenuCommand("Text Header", new ScheduledCommand() {
                @Override
                public void execute() {
                    column.setHeaderCaption("Text Header");
                }
            }, "Component", "Columns", "Column " + i, "Header Type");
            addMenuCommand("HTML Header", new ScheduledCommand() {
                @Override
                public void execute() {
                    grid.getHeaderRow(0).getCell(column)
                            .setHtml("HTML Header");
                }
            }, "Component", "Columns", "Column " + i, "Header Type");
            addMenuCommand("Widget Header", new ScheduledCommand() {
                @Override
                public void execute() {
                    final Button button = new Button("Button Header");
                    button.addClickHandler(new ClickHandler() {

                        @Override
                        public void onClick(ClickEvent event) {
                            button.setText("Clicked");
                        }
                    });
                    grid.getHeaderRow(0).getCell(column).setWidget(button);
                }
            }, "Component", "Columns", "Column " + i, "Header Type");

            // Footer types
            addMenuCommand("Text Footer", new ScheduledCommand() {
                @Override
                public void execute() {
                    grid.getFooterRow(0).getCell(column).setText("Text Footer");
                }
            }, "Component", "Columns", "Column " + i, "Footer Type");
            addMenuCommand("HTML Footer", new ScheduledCommand() {
                @Override
                public void execute() {
                    grid.getFooterRow(0).getCell(column)
                            .setHtml("HTML Footer");
                }
            }, "Component", "Columns", "Column " + i, "Footer Type");
            addMenuCommand("Widget Footer", new ScheduledCommand() {
                @Override
                public void execute() {
                    final Button button = new Button("Button Footer");
                    button.addClickHandler(new ClickHandler() {

                        @Override
                        public void onClick(ClickEvent event) {
                            button.setText("Clicked");
                        }
                    });
                    grid.getFooterRow(0).getCell(column).setWidget(button);
                }
            }, "Component", "Columns", "Column " + i, "Footer Type");

            // Renderer throwing exceptions
            addMenuCommand("Broken renderer", new ScheduledCommand() {
                @Override
                public void execute() {
                    final Renderer<Object> originalRenderer = (Renderer<Object>) column
                            .getRenderer();

                    column.setRenderer(new Renderer<Object>() {
                        @Override
                        public void render(RendererCellReference cell,
                                Object data) {
                            if (cell.getRowIndex() == cell.getColumnIndex()) {
                                throw new RuntimeException("I'm broken");
                            }
                            originalRenderer.render(cell, data);
                        }
                    });
                }
            }, "Component", "Columns", "Column " + i);
            addMenuCommand("Move column left", new ScheduledCommand() {

                @SuppressWarnings("unchecked")
                @Override
                public void execute() {
                    List<Column<?, List<Data>>> cols = grid.getColumns();
                    ArrayList<Column> reordered = new ArrayList<>(cols);
                    final int index = cols.indexOf(column);
                    if (index == 0) {
                        Column<?, List<Data>> col = reordered.remove(0);
                        reordered.add(col);
                    } else {
                        Column<?, List<Data>> col = reordered.remove(index);
                        reordered.add(index - 1, col);
                    }
                    grid.setColumnOrder(
                            reordered.toArray(new Column[reordered.size()]));
                }
            }, "Component", "Columns", "Column " + i);
        }
    }

    private int headerCounter = 0;
    private int footerCounter = 0;

    private void setHeaderTexts(HeaderRow row) {
        for (int i = 0; i < COLUMNS; ++i) {
            String caption = "Header (" + headerCounter + "," + i + ")";

            // Lets use some different cell types
            if (i % 3 == 0) {
                row.getCell(grid.getColumn(i)).setText(caption);
            } else if (i % 2 == 0) {
                row.getCell(grid.getColumn(i))
                        .setHtml("" + caption + "");
            } else {
                row.getCell(grid.getColumn(i)).setWidget(new HTML(caption));
            }
        }
        headerCounter++;
    }

    private void setFooterTexts(FooterRow row) {
        for (int i = 0; i < COLUMNS; ++i) {
            String caption = "Footer (" + footerCounter + "," + i + ")";

            // Lets use some different cell types
            if (i % 3 == 0) {
                row.getCell(grid.getColumn(i)).setText(caption);
            } else if (i % 2 == 0) {
                row.getCell(grid.getColumn(i))
                        .setHtml("" + caption + "");
            } else {
                row.getCell(grid.getColumn(i)).setWidget(new HTML(caption));
            }
        }
        footerCounter++;
    }

    private void createHeaderMenu() {
        final String[] menuPath = { "Component", "Header" };

        addMenuCommand("Visible", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setHeaderVisible(!grid.isHeaderVisible());
            }
        }, menuPath);

        addMenuCommand("Top", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setDefaultHeaderRow(grid.getHeaderRow(0));
            }
        }, "Component", "Header", "Default row");
        addMenuCommand("Bottom", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setDefaultHeaderRow(
                        grid.getHeaderRow(grid.getHeaderRowCount() - 1));
            }
        }, "Component", "Header", "Default row");
        addMenuCommand("Unset", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setDefaultHeaderRow(null);
            }
        }, "Component", "Header", "Default row");

        addMenuCommand("Prepend row", new ScheduledCommand() {
            @Override
            public void execute() {
                configureHeaderRow(grid.prependHeaderRow());
            }
        }, menuPath);
        addMenuCommand("Append row", new ScheduledCommand() {
            @Override
            public void execute() {
                configureHeaderRow(grid.appendHeaderRow());
            }
        }, menuPath);
        addMenuCommand("Remove top row", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.removeHeaderRow(0);
            }
        }, menuPath);
        addMenuCommand("Remove bottom row", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.removeHeaderRow(grid.getHeaderRowCount() - 1);
            }
        }, menuPath);

    }

    private void configureHeaderRow(final HeaderRow row) {
        setHeaderTexts(row);
        String rowTitle = "Row " + grid.getHeaderRowCount();
        final String[] menuPath = { "Component", "Header", rowTitle };

        addMenuCommand("Join column cells 0, 1", new ScheduledCommand() {

            @Override
            public void execute() {
                row.join(row.getCell(grid.getColumn(0)),
                        row.getCell(grid.getColumn(1)))
                        .setText("Join column cells 0, 1");

            }
        }, menuPath);

        addMenuCommand("Join columns 1, 2", new ScheduledCommand() {

            @Override
            public void execute() {
                row.join(grid.getColumn(1), grid.getColumn(2))
                        .setText("Join columns 1, 2");
                ;

            }
        }, menuPath);

        addMenuCommand("Join columns 3, 4, 5", new ScheduledCommand() {

            @Override
            public void execute() {
                row.join(grid.getColumn(3), grid.getColumn(4),
                        grid.getColumn(5)).setText("Join columns 3, 4, 5");

            }
        }, menuPath);

        addMenuCommand("Join all columns", new ScheduledCommand() {

            @Override
            public void execute() {
                row.join(grid.getColumns()
                        .toArray(new Grid.Column[grid.getColumnCount()]))
                        .setText("Join all columns");
                ;

            }
        }, menuPath);
    }

    private void createFooterMenu() {
        final String[] menuPath = { "Component", "Footer" };

        addMenuCommand("Visible", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setFooterVisible(!grid.isFooterVisible());
            }
        }, menuPath);

        addMenuCommand("Prepend row", new ScheduledCommand() {
            @Override
            public void execute() {
                configureFooterRow(grid.prependFooterRow());
            }
        }, menuPath);
        addMenuCommand("Append row", new ScheduledCommand() {
            @Override
            public void execute() {
                configureFooterRow(grid.appendFooterRow());
            }
        }, menuPath);
        addMenuCommand("Remove top row", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.removeFooterRow(0);
            }
        }, menuPath);
        addMenuCommand("Remove bottom row", new ScheduledCommand() {
            @Override
            public void execute() {
                assert grid.getFooterRowCount() > 0;
                grid.removeFooterRow(grid.getFooterRowCount() - 1);
            }
        }, menuPath);
    }

    private void createEditorMenu() {
        addMenuCommand("Enabled", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setEditorEnabled(!grid.isEditorEnabled());
            }
        }, "Component", "Editor");

        addMenuCommand("Edit row 5", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.editRow(5);
            }
        }, "Component", "Editor");

        addMenuCommand("Edit row 100", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.editRow(100);
            }
        }, "Component", "Editor");

        addMenuCommand("Save", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.saveEditor();
            }
        }, "Component", "Editor");

        addMenuCommand("Cancel edit", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.cancelEditor();
            }
        }, "Component", "Editor");

        addMenuCommand("Change Save Caption", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setEditorSaveCaption("ǝʌɐS");
            }
        }, "Component", "Editor");

        addMenuCommand("Change Cancel Caption", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setEditorCancelCaption("ʃǝɔuɐↃ");
            }
        }, "Component", "Editor");

        addMenuCommand("Toggle second editor error", new ScheduledCommand() {
            @Override
            public void execute() {
                secondEditorError = !secondEditorError;
            }
        }, "Component", "Editor");
    }

    private void configureFooterRow(final FooterRow row) {
        setFooterTexts(row);
        String rowTitle = "Row " + grid.getFooterRowCount();
        final String[] menuPath = { "Component", "Footer", rowTitle };

        addMenuCommand("Join column cells 0, 1", new ScheduledCommand() {

            @Override
            public void execute() {
                row.join(row.getCell(grid.getColumn(0)),
                        row.getCell(grid.getColumn(1)))
                        .setText("Join column cells 0, 1");

            }
        }, menuPath);

        addMenuCommand("Join columns 1, 2", new ScheduledCommand() {

            @Override
            public void execute() {
                row.join(grid.getColumn(1), grid.getColumn(2))
                        .setText("Join columns 1, 2");
                ;

            }
        }, menuPath);

        addMenuCommand("Join all columns", new ScheduledCommand() {

            @Override
            public void execute() {
                row.join(grid.getColumns()
                        .toArray(new Grid.Column[grid.getColumnCount()]))
                        .setText("Join all columns");
                ;

            }
        }, menuPath);
    }

    private void createDataSourceMenu() {
        final String[] menuPath = { "Component", "DataSource" };

        addMenuCommand("Reset with 100 rows of Data", new ScheduledCommand() {
            @Override
            public void execute() {
                ds.asList().clear();
                data = createData(100);
                ds.asList().addAll(data);
            }
        }, menuPath);

        addMenuCommand("Reset with " + ROWS + " rows of Data",
                new ScheduledCommand() {
                    @Override
                    public void execute() {
                        ds.asList().clear();
                        data = createData(ROWS);
                        ds.asList().addAll(data);
                    }
                }, menuPath);
    }

    /**
     * Creates a renderer for a {@link Renderers}
     */
    @SuppressWarnings("rawtypes")
    private final Renderer createRenderer(Renderers renderer) {
        switch (renderer) {
        case TEXT_RENDERER:
            return new TextRenderer();

        case HTML_RENDERER:
            return new HtmlRenderer() {

                @Override
                public void render(RendererCellReference cell,
                        String htmlString) {
                    super.render(cell, "" + htmlString + "");
                }
            };

        case NUMBER_RENDERER:
            return new NumberRenderer();

        case DATE_RENDERER:
            return new DateRenderer();

        default:
            return new TextRenderer();
        }
    }

    /**
     * Creates a collection of handlers for all the grid key events
     */
    private void createKeyHandlers() {
        final List<VLabel> labels = new ArrayList<>();
        for (int i = 0; i < 9; ++i) {
            VLabel tmp = new VLabel();
            addNorth(tmp, 20);
            labels.add(tmp);
        }

        // Key Down Events
        grid.addBodyKeyDownHandler(new BodyKeyDownHandler() {
            private final VLabel label = labels.get(0);

            @Override
            public void onKeyDown(GridKeyDownEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        grid.addHeaderKeyDownHandler(new HeaderKeyDownHandler() {
            private final VLabel label = labels.get(1);

            @Override
            public void onKeyDown(GridKeyDownEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        grid.addFooterKeyDownHandler(new FooterKeyDownHandler() {
            private final VLabel label = labels.get(2);

            @Override
            public void onKeyDown(GridKeyDownEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        // Key Up Events
        grid.addBodyKeyUpHandler(new BodyKeyUpHandler() {
            private final VLabel label = labels.get(3);

            @Override
            public void onKeyUp(GridKeyUpEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        grid.addHeaderKeyUpHandler(new HeaderKeyUpHandler() {
            private final VLabel label = labels.get(4);

            @Override
            public void onKeyUp(GridKeyUpEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        grid.addFooterKeyUpHandler(new FooterKeyUpHandler() {
            private final VLabel label = labels.get(5);

            @Override
            public void onKeyUp(GridKeyUpEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        // Key Press Events
        grid.addBodyKeyPressHandler(new BodyKeyPressHandler() {
            private final VLabel label = labels.get(6);

            @Override
            public void onKeyPress(GridKeyPressEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        grid.addHeaderKeyPressHandler(new HeaderKeyPressHandler() {
            private final VLabel label = labels.get(7);

            @Override
            public void onKeyPress(GridKeyPressEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

        grid.addFooterKeyPressHandler(new FooterKeyPressHandler() {
            private final VLabel label = labels.get(8);

            @Override
            public void onKeyPress(GridKeyPressEvent event) {
                CellReference<?> focused = event.getFocusedCell();
                updateLabel(label, event.toDebugString(), focused.getRowIndex(),
                        focused.getColumnIndex());
            }
        });

    }

    private void updateLabel(VLabel label, String output, int object,
            int column) {
        String coords = "(" + object + ", " + column + ")";
        label.setText(coords + " " + output);
    }

    private void createDetailsMenu() {
        String[] menupath = new String[] { "Component", "Row details" };
        addMenuCommand("Set generator", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setDetailsGenerator(new DetailsGenerator() {
                    @Override
                    public Widget getDetails(int rowIndex) {
                        FlowPanel panel = new FlowPanel();

                        final Label label = new Label("Row: " + rowIndex + ".");
                        Button button = new Button("Button",
                                new ClickHandler() {
                                    @Override
                                    public void onClick(ClickEvent event) {
                                        label.setText("clicked");
                                    }
                                });

                        panel.add(label);
                        panel.add(button);
                        return panel;
                    }
                });
            }
        }, menupath);

        addMenuCommand("Set faulty generator", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setDetailsGenerator(new DetailsGenerator() {
                    @Override
                    public Widget getDetails(int rowIndex) {
                        throw new RuntimeException("This is by design.");
                    }
                });
            }
        }, menupath);

        addMenuCommand("Set empty generator", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setDetailsGenerator(new DetailsGenerator() {
                    /*
                     * While this is functionally equivalent to the NULL
                     * generator, it's good to be explicit, since the behavior
                     * isn't strictly tied between them. NULL generator might be
                     * changed to render something different by default, and an
                     * empty generator might behave differently also in the
                     * future.
                     */

                    @Override
                    public Widget getDetails(int rowIndex) {
                        return null;
                    }
                });
            }
        }, menupath);

        String[] togglemenupath = new String[] { menupath[0], menupath[1],
                "Toggle details for..." };
        for (int i : new int[] { 0, 1, 100, 200, 300, 400, 500, 600, 700, 800,
                900, 999 }) {
            final int rowIndex = i;
            addMenuCommand("Row " + rowIndex, new ScheduledCommand() {
                boolean visible = false;

                @Override
                public void execute() {
                    visible = !visible;
                    grid.setDetailsVisible(rowIndex, visible);
                }
            }, togglemenupath);
        }

    }

    private static Logger getLogger() {
        return Logger.getLogger(GridBasicClientFeaturesWidget.class.getName());
    }

    private void createSidebarMenu() {
        String[] menupath = new String[] { "Component", "Sidebar" };

        final List<MenuItem> customMenuItems = new ArrayList<>();
        final List<MenuItemSeparator> separators = new ArrayList<>();

        addMenuCommand("Add item to end", new ScheduledCommand() {
            @Override
            public void execute() {
                MenuItem item = createSidebarMenuItem(customMenuItems.size());
                customMenuItems.add(item);
                grid.getSidebarMenu().addItem(item);
            }
        }, menupath);

        addMenuCommand("Add item before index 1", new ScheduledCommand() {
            @Override
            public void execute() {
                MenuItem item = createSidebarMenuItem(customMenuItems.size());
                customMenuItems.add(item);
                grid.getSidebarMenu().insertItem(item, 1);
            }
        }, menupath);

        addMenuCommand("Remove last added item", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.getSidebarMenu().removeItem(
                        customMenuItems.remove(customMenuItems.size() - 1));
            }
        }, menupath);

        addMenuCommand("Add separator to end", new ScheduledCommand() {
            @Override
            public void execute() {
                MenuItemSeparator separator = new MenuItemSeparator();
                separators.add(separator);
                grid.getSidebarMenu().addSeparator(separator);
            }
        }, menupath);

        addMenuCommand("Add separator before index 1", new ScheduledCommand() {
            @Override
            public void execute() {
                MenuItemSeparator separator = new MenuItemSeparator();
                separators.add(separator);
                grid.getSidebarMenu().insertSeparator(separator, 1);
            }
        }, menupath);

        addMenuCommand("Remove last added separator", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.getSidebarMenu().removeSeparator(
                        separators.remove(separators.size() - 1));
            }
        }, menupath);

        addMenuCommand("Toggle sidebar visibility", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setSidebarOpen(!grid.isSidebarOpen());
            }
        }, menupath);

        addMenuCommand("Open sidebar and disable grid", new ScheduledCommand() {
            @Override
            public void execute() {
                grid.setSidebarOpen(true);

                Scheduler.get()
                        .scheduleFixedDelay(new Scheduler.RepeatingCommand() {
                            @Override
                            public boolean execute() {
                                if (grid.isSidebarOpen()) {
                                    grid.setEnabled(false);

                                    return false;
                                }

                                return true;
                            }
                        }, 250);
            }
        }, menupath);
    }

    private MenuItem createSidebarMenuItem(final int index) {
        final MenuItem menuItem = new MenuItem("Custom menu item " + index,
                new ScheduledCommand() {
                    @Override
                    public void execute() {
                        if (index % 2 == 0) {
                            grid.setSidebarOpen(false);
                        }
                        getLogger().info("Menu item " + index + " selected");
                    }
                });
        return menuItem;
    }
}


text:
@implementation BkCoreMac

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

@end

redpajama_set_name: RedPajamaGithub


text:
VBASE=/media
if [ -d /srv/media ]; then
  VBASE=/srv/media
fi

call_filebot() {
    # Usage call_filebot movie [TEST] file [...]
    #       call_filebot music [TEST] [multidisc] [various|soundtrack|showtunes|virtual artist] file [...]
    #       call_filebot tvshow|anime [TEST] DVD|DOWNLOAD [RES]
    #           Optional "res" will include video resolution in the filename
    type=$1
    shift
    dryrun=""
    if [ "$1" = "TEST" ]; then
        dryrun=1
        shift
    fi
    case $type in
        movie)
            args="-rename -non-strict --db TheMovieDB"
            format='{plex.derive{" $audioLanguages"}{" [$resolution]"}}'
            output=${VBASE}/video/DVDs/
            ;;
        music)
            args='-rename -non-strict --db ID3'
	    multidisc=
	    format='{artist}/{album+'\''/'\''}{pi.pad(2)} {t}'
	    if [ $1 = "multidisc" ]; then
		multidisc=1
		shift
            fi
	    case $1 in
	        virtual)
		    shift
		    artist=$1
		    shift
	            format='['${artist}']/{album+'\''/'\''}{pi.pad(2)} {t}'
		    ;;
	        various)
		    shift
	            format='Various Artists/{album+'\''/'\''}{pi.pad(2)} {t} ({artist})'
		    ;;
	        showtunes)
		    shift
	            format='Showtunes/{album+'\''/'\''}{pi.pad(2)} {t} ({artist})'
		    ;;
	        soundtrack)
		    shift
	            format='Soundtracks/{album+'\''/'\''}{pi.pad(2)} {t} ({artist})'
		    ;;
	    esac
	    # Change track number in format for multidisc
	    if [ -n "$multidisc" ]; then
	        format="$(echo $format | sed 's/{pi.pad(2)/{media.Part}{media.PartPosition}-{pi.pad(2)/')"
	    fi
            output=${VBASE}/mp3/
            ;;
        tvshow|anime)
            format='{plex.tail}'
            case $1 in
                DVD)
                    output="${VBASE}/video/DVDs/TV_Shows/"
                    shift
                    ;;
                DOWNLOAD)
                    output="${VBASE}/video/TV/"
                    shift
                    ;;
                *)
                    echo "ERROR: unknown TV type, must be DVD or DOWNLOAD!"
                    exit 1
                    ;;
            esac
            if [ "$1" = "RES" ]; then
                format='{plex.derive{" [$resolution]"}.tail}'
                if [ $type = "anime" ]; then
                    format='{localize.English.plex.derive{" [$resolution]"}.tail}'
                fi
                shift
            fi
            args="-rename -non-strict --db TheTVDB"
            if [ $type = "anime" ]; then
                #format='{localize.English.plex.tail}'
                format='{localize.English.n}/{localize.English.n} - {absolute.pad(episodelist.size() < 99 ? 2 : 3)} - {localize.English.t}'
                args="-rename -non-strict --db AniDB --lang English"
            fi
            ;;
        *)
            echo 'Unknown file type "$type"!'
            exit 1
            ;;
    esac
    if [ -n "$dryrun" ]; then
        args="$args --action TEST"
    fi
    set -x
    filebot $=args --format $format --output $output $*
    set +x
}

# Movie aliases
alias fbmovie='call_filebot movie'
alias fbmovietest='call_filebot movie TEST'
# Music alises
alias fbmusic='call_filebot music'
alias fbmusictest='call_filebot music TEST'
alias fbmusicmd='call_filebot music multidisc'
alias fbmusicmdtest='call_filebot music TEST multidisc'
alias fbmusicvdis='call_filebot music virtual disney'
alias fbmusicvdistest='call_filebot music TEST virtual disney'
alias fbmusicmdvdis='call_filebot music multidisc virtual disney'
alias fbmusicmdvdistest='call_filebot music TEST multidisc virtual disney'
alias fbmusicvar='call_filebot music various'
alias fbmusicvartest='call_filebot music TEST various'
alias fbmusicmdvar='call_filebot music multidisc various'
alias fbmusicmdvartest='call_filebot music TEST multidisc various'
alias fbmusicsh='call_filebot music showtunes'
alias fbmusicshtest='call_filebot music TEST showtunes'
alias fbmusicmdsh='call_filebot music multidisc showtunes'
alias fbmusicmdshtest='call_filebot music TEST multidisc showtunes'
alias fbmusicst='call_filebot music soundtrack'
alias fbmusicsttest='call_filebot music TEST soundtrack'
alias fbmusicmdst='call_filebot music multidisc soundtrack'
alias fbmusicmdsttest='call_filebot music TEST multidisc soundtrack'
# TV show aliass
alias fbdvdtv='call_filebot tvshow DVD'
alias fbdvdtvtest='call_filebot tvshow TEST DVD'
alias fbdvdtvres='call_filebot tvshow DVD RES'
alias fbdvdtvrestest='call_filebot tvshow TEST DVD RES'
alias fbdltv='call_filebot tvshow DOWNLOAD'
alias fbdltvtest='call_filebot tvshow TEST DOWNLOAD'
alias fbdltvres='call_filebot tvshow DOWNLOAD RES'
alias fbdltvrestest='call_filebot tvshow TEST DOWNLOAD RES'
# Anime aliases
alias fbdvdanime='call_filebot anime DVD'
alias fbdvdanimetest='call_filebot anime TEST DVD'
alias fbdvdanimeres='call_filebot anime DVD RES'
alias fbdvdanimerestest='call_filebot anime TEST DVD RES'
alias fbdlanime='call_filebot anime DOWNLOAD'
alias fbdlanimetest='call_filebot anime TEST DOWNLOAD'
alias fbdlanimeres='call_filebot anime DOWNLOAD RES'
alias fbdlanimerestest='call_filebot anime TEST DOWNLOAD RES'

# Fix plex ownership and permissions
plexperms () {
  dir=${1:-.}
  sudo chown -R plex:plex $dir
  sudo chmod -R g+rw,a+r $dir
}
mp3perms () {
  for d in $*; do
    dir=${d:-.}
    sudo chgrp -R mp3 $dir
    sudo chmod -R g+rw,a+r $dir
    find $dir -type d -print0 | xargs -0 sudo chmod g+s
  done
}

# Youtube DL alias for filebot
ytdltv() {
  usage() {
    if [ -n "$1" ]; then
      echo $1
    fi
    echo "usage: ytdltv [show_name] S##E## url"
    return 1
  }
  show="."
  if [ "$#" -gt 2 ]; then	# If no first arg, use pwd as show name
    show=$1
    shift
  fi
  se=$1
  url=$2
  ret=
  if [ -z "$show" -o -z "$se" -o -z "$url" ]; then
    usage
    ret=$(( $? > 0 ))
  fi
  if [ "$show" = "." ]; then
    show="$(pwd | sed 's/^.*\///')"
  fi
  if [[ $se =~ 'S[0-9]*E[0-9]*' ]]; then
    :
  else
    usage "ERROR $se does not match S##E##"
    ret=$(( $? > 0 ))
  fi
  if [ -z "$ret" -o "$ret" = 0 ]; then
    #echo youtube-dl -o "\"$show - $se %(title)s.%(ext)s\"" $url
    #youtube-dl -o "$show - $se %(title)s.%(ext)s" $url
    echo yt-dlp -o "\"$show - $se %(title)s.%(ext)s\"" $url
    yt-dlp -o "$show - $se %(title)s.%(ext)s" $url
  fi
  call_filebot tvshow DOWNLOAD *"$se"*
}

# Remove [xxx] from youtube downloads
ytrename() {
  for f in *\[*\].*; do
    n=$(echo $f | sed 's/[[:space:]]*\[[^]]*\]\././')
    mv "$f" "$n"
  done
}


text:
import {A11yModule, CDK_DESCRIBEDBY_HOST_ATTRIBUTE} from '../index';
import {AriaDescriber, MESSAGES_CONTAINER_ID} from './aria-describer';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {Component, ElementRef, ViewChild, Provider} from '@angular/core';
import {Platform} from '@angular/cdk/platform';

describe('AriaDescriber', () => {
  let ariaDescriber: AriaDescriber;
  let component: TestApp;
  let fixture: ComponentFixture<TestApp>;

  function createFixture(providers: Provider[] = []) {
    TestBed.configureTestingModule({
      imports: [A11yModule],
      declarations: [TestApp],
      providers: [AriaDescriber, ...providers],
    }).compileComponents();

    fixture = TestBed.createComponent(TestApp);
    component = fixture.componentInstance;
    ariaDescriber = component.ariaDescriber;
    fixture.detectChanges();
  }

  afterEach(() => {
    ariaDescriber.ngOnDestroy();
  });

  it('should initialize without the message container', () => {
    createFixture();
    expect(getMessagesContainer()).toBeNull();
  });

  it('should be able to create a message element', () => {
    createFixture();
    ariaDescriber.describe(component.element1, 'My Message');
    expectMessages(['My Message']);
  });

  it('should be able to describe using an element', () => {
    createFixture();
    const descriptionNode = fixture.nativeElement.querySelector('#description-with-existing-id');
    ariaDescriber.describe(component.element1, descriptionNode);
    expectMessage(component.element1, 'Hello');
  });

  it('should hide the message container', () => {
    createFixture();
    ariaDescriber.describe(component.element1, 'My Message');
    expect(getMessagesContainer().classList).toContain('cdk-visually-hidden');
  });

  it('should not register empty strings', () => {
    createFixture();
    ariaDescriber.describe(component.element1, '');
    expect(getMessageElements()).toBe(null);
  });

  it('should not register non-string values', () => {
    createFixture();
    expect(() => ariaDescriber.describe(component.element1, null!)).not.toThrow();
    expect(getMessageElements()).toBe(null);
  });

  it('should not throw when trying to remove non-string value', () => {
    createFixture();
    expect(() => ariaDescriber.removeDescription(component.element1, null!)).not.toThrow();
  });

  it('should de-dupe a message registered multiple times', () => {
    createFixture();
    ariaDescriber.describe(component.element1, 'My Message');
    ariaDescriber.describe(component.element2, 'My Message');
    ariaDescriber.describe(component.element3, 'My Message');
    expectMessages(['My Message']);
    expectMessage(component.element1, 'My Message');
    expectMessage(component.element2, 'My Message');
    expectMessage(component.element3, 'My Message');
  });

  it('should de-dupe a message registered multiple via an element node', () => {
    createFixture();
    const descriptionNode = fixture.nativeElement.querySelector('#description-with-existing-id');
    ariaDescriber.describe(component.element1, descriptionNode);
    ariaDescriber.describe(component.element2, descriptionNode);
    ariaDescriber.describe(component.element3, descriptionNode);
    expectMessage(component.element1, 'Hello');
    expectMessage(component.element2, 'Hello');
    expectMessage(component.element3, 'Hello');
  });

  it('should be able to register multiple messages', () => {
    createFixture();
    ariaDescriber.describe(component.element1, 'First Message');
    ariaDescriber.describe(component.element2, 'Second Message');
    expectMessages(['First Message', 'Second Message']);
    expectMessage(component.element1, 'First Message');
    expectMessage(component.element2, 'Second Message');
  });

  it('should be able to unregister messages', () => {
    createFixture();
    ariaDescriber.describe(component.element1, 'My Message');
    expectMessages(['My Message']);

    // Register again to check dedupe
    ariaDescriber.describe(component.element2, 'My Message');
    expectMessages(['My Message']);

    // Unregister one message and make sure the message is still present in the container
    ariaDescriber.removeDescription(component.element1, 'My Message');
    expect(component.element1.hasAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE)).toBeFalsy();
    expectMessages(['My Message']);

    // Unregister the second message, message container should be gone
    ariaDescriber.removeDescription(component.element2, 'My Message');
    expect(component.element2.hasAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE)).toBeFalsy();
    expect(getMessagesContainer()).toBeNull();
  });

  it('should not remove nodes that were set as messages when unregistering', () => {
    createFixture();
    const descriptionNode = fixture.nativeElement.querySelector('#description-with-existing-id');

    expect(document.body.contains(descriptionNode))
        .toBe(true, 'Expected node to be inside the document to begin with.');
    expect(getMessagesContainer()).toBeNull('Expected no messages container on init.');

    ariaDescriber.describe(component.element1, descriptionNode);

    expectMessage(component.element1, 'Hello');
    expect(getMessagesContainer())
        .toBeNull('Expected no messages container after the element was described.');

    ariaDescriber.removeDescription(component.element1, descriptionNode);

    expect(document.body.contains(descriptionNode)).toBe(true,
        'Expected description node to still be in the DOM after it is no longer being used.');
  });

  it('should keep nodes set as descriptions inside their original position in the DOM', () => {
    createFixture();
    const descriptionNode = fixture.nativeElement.querySelector('#description-with-existing-id');
    const initialParent = descriptionNode.parentNode;

    expect(initialParent).toBeTruthy('Expected node to have a parent initially.');

    ariaDescriber.describe(component.element1, descriptionNode);

    expectMessage(component.element1, 'Hello');
    expect(descriptionNode.parentNode).toBe(initialParent,
        'Expected node to stay inside the same parent when used as a description.');

    ariaDescriber.removeDescription(component.element1, descriptionNode);

    expect(descriptionNode.parentNode).toBe(initialParent,
      'Expected node to stay inside the same parent after not being used as a description.');
  });

  it('should be able to unregister messages while having others registered', () => {
    createFixture();
    ariaDescriber.describe(component.element1, 'Persistent Message');
    ariaDescriber.describe(component.element2, 'My Message');
    expectMessages(['Persistent Message', 'My Message']);

    // Register again to check dedupe
    ariaDescriber.describe(component.element3, 'My Message');
    expectMessages(['Persistent Message', 'My Message']);

    // Unregister one message and make sure the message is still present in the container
    ariaDescriber.removeDescription(component.element2, 'My Message');
    expectMessages(['Persistent Message', 'My Message']);

    // Unregister the second message, message container should be gone
    ariaDescriber.removeDescription(component.element3, 'My Message');
    expectMessages(['Persistent Message']);
  });

  it('should be able to append to an existing list of aria describedby', () => {
    createFixture();
    ariaDescriber.describe(component.element4, 'My Message');
    expectMessages(['My Message']);
    expectMessage(component.element4, 'My Message');
  });

  it('should be able to handle multiple regisitrations of the same message to an element', () => {
    createFixture();
    ariaDescriber.describe(component.element1, 'My Message');
    ariaDescriber.describe(component.element1, 'My Message');
    expectMessages(['My Message']);
    expectMessage(component.element1, 'My Message');
  });

  it('should not throw when attempting to describe a non-element node', () => {
    createFixture();
    const node: any = document.createComment('Not an element node');
    expect(() => ariaDescriber.describe(node, 'This looks like an element')).not.toThrow();
  });

  it('should clear any pre-existing containers', () => {
    createFixture();
    const extraContainer = document.createElement('div');
    extraContainer.id = MESSAGES_CONTAINER_ID;
    document.body.appendChild(extraContainer);

    ariaDescriber.describe(component.element1, 'Hello');

    // Use `querySelectorAll` with an attribute since `getElementById` will stop at the first match.
    expect(document.querySelectorAll(`[id='${MESSAGES_CONTAINER_ID}']`).length).toBe(1);

    if (extraContainer.parentNode) {
      extraContainer.parentNode.removeChild(extraContainer);
    }
  });

  it('should not describe messages that match up with the aria-label of the element', () => {
    createFixture();
    component.element1.setAttribute('aria-label', 'Hello');
    ariaDescriber.describe(component.element1, 'Hello');
    ariaDescriber.describe(component.element1, 'Hi');
    expectMessages(['Hi']);
  });

  it('should assign an id to the description element, if it does not have one', () => {
    createFixture();
    const descriptionNode = fixture.nativeElement.querySelector('[description-without-id]');
    expect(descriptionNode.getAttribute('id')).toBeFalsy();
    ariaDescriber.describe(component.element1, descriptionNode);
    expect(descriptionNode.getAttribute('id')).toBeTruthy();
  });

  it('should not overwrite the existing id of the description element', () => {
    createFixture();
    const descriptionNode = fixture.nativeElement.querySelector('#description-with-existing-id');
    expect(descriptionNode.id).toBe('description-with-existing-id');
    ariaDescriber.describe(component.element1, descriptionNode);
    expect(descriptionNode.id).toBe('description-with-existing-id');
  });

  it('should not remove pre-existing description nodes on destroy', () => {
    createFixture();
    const descriptionNode = fixture.nativeElement.querySelector('#description-with-existing-id');

    expect(document.body.contains(descriptionNode))
        .toBe(true, 'Expected node to be inside the document to begin with.');

    ariaDescriber.describe(component.element1, descriptionNode);

    expectMessage(component.element1, 'Hello');
    expect(component.element1.hasAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE)).toBe(true);

    ariaDescriber.ngOnDestroy();

    expect(component.element1.hasAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE)).toBe(false);
    expect(document.body.contains(descriptionNode)).toBe(true,
        'Expected description node to still be in the DOM after it is no longer being used.');
  });

  it('should remove the aria-describedby attribute if there are no more messages', () => {
    createFixture();
    const element = component.element1;

    expect(element.hasAttribute('aria-describedby')).toBe(false);

    ariaDescriber.describe(component.element1, 'Message');
    expect(element.hasAttribute('aria-describedby')).toBe(true);

    ariaDescriber.removeDescription(component.element1, 'Message');
    expect(element.hasAttribute('aria-describedby')).toBe(false);
  });

  it('should set `aria-hidden` on the container by default', () => {
    createFixture([{provide: Platform, useValue: {BLINK: true}}]);
    ariaDescriber.describe(component.element1, 'My Message');
    expect(getMessagesContainer().getAttribute('aria-hidden')).toBe('true');
  });

  it('should disable `aria-hidden` on the container in IE', () => {
    createFixture([{provide: Platform, useValue: {TRIDENT: true}}]);
    ariaDescriber.describe(component.element1, 'My Message');
    expect(getMessagesContainer().getAttribute('aria-hidden')).toBe('false');
  });

  it('should disable `aria-hidden` on the container in Edge', () => {
    createFixture([{provide: Platform, useValue: {EDGE: true}}]);
    ariaDescriber.describe(component.element1, 'My Message');
    expect(getMessagesContainer().getAttribute('aria-hidden')).toBe('false');
  });
});

function getMessagesContainer() {
  return document.querySelector(`#${MESSAGES_CONTAINER_ID}`)!;
}

function getMessageElements(): Node[] | null {
  const messagesContainer = getMessagesContainer();
  if (!messagesContainer) { return null; }

  return messagesContainer ?  Array.prototype.slice.call(messagesContainer.children) : null;
}

/** Checks that the messages array matches the existing created message elements. */
function expectMessages(messages: string[]) {
  const messageElements = getMessageElements();
  expect(messageElements).toBeDefined();

  expect(messages.length).toBe(messageElements!.length);
  messages.forEach((message, i) => {
    expect(messageElements![i].textContent).toBe(message);
  });
}

/** Checks that an element points to a message element that contains the message. */
function expectMessage(el: Element, message: string) {
  const ariaDescribedBy = el.getAttribute('aria-describedby');
  expect(ariaDescribedBy).toBeDefined();

  const cdkDescribedBy = el.getAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
  expect(cdkDescribedBy).toBeDefined();

  const messages = ariaDescribedBy!.split(' ').map(referenceId => {
    const messageElement = document.querySelector(`#${referenceId}`);
    return messageElement ? messageElement.textContent : '';
  });

  expect(messages).toContain(message);
}

@Component({
  template: `

Hello

Hey

  `,
})
class TestApp {
  @ViewChild('element1') _element1: ElementRef<HTMLElement>;
  get element1(): Element { return this._element1.nativeElement; }

  @ViewChild('element2') _element2: ElementRef<HTMLElement>;
  get element2(): Element { return this._element2.nativeElement; }

  @ViewChild('element3') _element3: ElementRef<HTMLElement>;
  get element3(): Element { return this._element3.nativeElement; }

  @ViewChild('element4') _element4: ElementRef<HTMLElement>;
  get element4(): Element { return this._element4.nativeElement; }

  constructor(public ariaDescriber: AriaDescriber) { }
}


text:
 Compares object with TermLabel

**Namespace:** [OfficeDevPnP.Core.Framework.Provisioning.Model](OfficeDevPnP.Core.Framework.Provisioning.Model.md)
**Assembly:** OfficeDevPnP.Core.dll
## Syntax
```C#
public override bool Equals(Object obj)
```
### Parameters
#### obj
  Type: System.Object
  Object that represents TermLabel

### Return Value
Type: bool
true if the current object is equal to the TermLabel

## See also
- [TermLabel](OfficeDevPnP.Core.Framework.Provisioning.Model.TermLabel.md)
- [OfficeDevPnP.Core.Framework.Provisioning.Model](OfficeDevPnP.Core.Framework.Provisioning.Model.md)


text:
A simple JAVA bot to grab web resources with lots of configuration (anonimity, user agent, wait before requests, auto compression, and etc). Mainly useful when you want to grab information from a web site.

More info: http://mirsamantajbakhsh.github.io/Microbot

Contact me: ms.tajbakhsh@urmia.ac.ir


text:
<service name="TestService" >
	<Description>
		Please Type your service description here
	</Description>
	<messageReceivers>
		<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
		<messageReceiver  mep="http://www.w3.org/2004/08/wsdl/in-out"  class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
	</messageReceivers>
	<parameter name="ServiceClass" locked="false">com.prd.axis2.TestService</parameter>
</service>


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>AGCLValidator</title>
<meta name="date" content="2014-06-11">
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method

org.osate.xtext.aadl2.agcl.validation

Class AGCLValidator

java.lang.Object

org.eclipse.xtext.validation.AbstractInjectableValidator

org.eclipse.xtext.validation.AbstractDeclarativeValidator

org.osate.xtext.aadl2.agcl.validation.AbstractAGCLValidator

org.osate.xtext.aadl2.agcl.validation.AGCLValidator

All Implemented Interfaces:

org.eclipse.emf.ecore.EValidator, org.eclipse.xtext.validation.ValidationMessageAcceptor

public class AGCLValidator
extends AbstractAGCLValidator

Custom validation rules.

 see http://www.eclipse.org/Xtext/documentation.html#validation

Nested Class Summary

Nested classes/interfaces inherited from class org.eclipse.xtext.validation.AbstractDeclarativeValidator

org.eclipse.xtext.validation.AbstractDeclarativeValidator.State, org.eclipse.xtext.validation.AbstractDeclarativeValidator.StateAccess

Nested classes/interfaces inherited from interface org.eclipse.emf.ecore.EValidator

org.eclipse.emf.ecore.EValidator.Descriptor, org.eclipse.emf.ecore.EValidator.PatternMatcher, org.eclipse.emf.ecore.EValidator.Registry, org.eclipse.emf.ecore.EValidator.SubstitutionLabelProvider, org.eclipse.emf.ecore.EValidator.ValidationDelegate

Field Summary

Fields inherited from class org.eclipse.xtext.validation.AbstractInjectableValidator

CURRENT_LANGUAGE_NAME, ISSUE_SEVERITIES

Fields inherited from interface org.eclipse.xtext.validation.ValidationMessageAcceptor

INSIGNIFICANT_INDEX

Fields inherited from interface org.eclipse.emf.ecore.EValidator

MARKER, RELATED_URIS_ATTRIBUTE, URI_ATTRIBUTE

Constructor Summary

Constructors

Constructor and Description

AGCLValidator()

Method Summary

Methods inherited from class org.eclipse.xtext.validation.AbstractDeclarativeValidator

acceptError, acceptError, acceptInfo, acceptInfo, acceptWarning, acceptWarning, getMessageAcceptor, setInjector, setMessageAcceptor

Methods inherited from class org.eclipse.xtext.validation.AbstractInjectableValidator

isLanguageSpecific, register, validate, validate, validate

Methods inherited from class java.lang.Object

equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Constructor Detail

AGCLValidator

public AGCLValidator()

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method


text:
title: 0.4.3.1
---

[https://github.com/Asnivor/MedLaunch/releases/tag/0.4.3.1](https://github.com/Asnivor/MedLaunch/releases/tag/0.4.3.1)

#### Important Release Notes
** This MedLaunch release is *ONLY* compatible with version 0.9.42.x of Mednafen. Do *NOT* upgrade if you are not planning to update Mednafen also **

**_This is primarily a bugfix release._**

**_If you are seeing MedLaunch crash whilst opening please either:_**

* **_Extract this version of MedLaunch to a new folder and run it_**

**_or_**

* **_Extract this version over your current MedLaunch folder, then delete MedLaunch.db from MedlaunchDIR\Data\Settings before running the application_**

Otherwise follow the usual instructions below.

#### Notable Additions
* (Bugfix) Fixed exception(crash) caused by mednafen application not being properly initialised before importing configs into MedLaunch
* (Bugfix) Added null-check on netplay servers datagrid (mitigates application exception if the database didnt initialise correctly with the pre-defined servers)
* (Bugfix) Fixed localisation lookup issue when attempting to determine the mednafen version from the mednafen output log (stdout.txt)
* (Addition) Added another public netplay server to the list

#### New Install
* Extract this release to a folder, run the 'MedLaunch.exe' executable and choose your Mednafen directory (must be the Mednafen 0.9.42.x branch - 64-bit version is required if you want to emulate Saturn games).
* You are then prompted to choose whether to import all config settings from your Mednafen folder into the MedLaunch database (this is recommended).
* If you currently use system-specific config files with Mednafen the settings from these will be imported with the above process. However MedLaunch will write to these files when you launch a game - so back them up somewhere if you are not happy with this.

#### Upgrade
##### Preferred Method:
* Automatically download and upgrade using the 'Updates' tab within MedLaunch itself.
* Ensure you have the correct version of Mednafen installed (v0.9.42.x)
* Once MedLaunch has upgraded, go to the 'Configs' tab and click the 'IMPORT ALL CONFIGS FROM DISK' button
* In settings change your mednafen directory if you installed the new version of mednafen somewhere else

##### Manual Method:
* You can safely extract this new release over an existing MedLaunch folder (providing you do not have MedLaunch running at the time)
* Once extracted run the MedLaunch.exe executable and your current database will be upgraded before the application starts proper.
* Once MedLaunch has upgraded, go to the 'Configs' tab and click the 'IMPORT ALL CONFIGS FROM DISK' button
* In settings change your mednafen directory if you installed the new version of mednafen somewhere else


text:
Edge

Genomes

Blast

    BLAST on Genome {{ genome.id }}:

      Program

        <select class="form-control" ng-model="program">
          <option value="blastn">blastn</option>
          <option value="tblastn">tblastn</option>
        </select>

    Query

    <textarea class="form-control sequence" ng-model="query"></textarea>
    <button class="btn btn-primary" ng-click="Blast(query, program)">
      BLAST
    </button>

      Waiting for server to respond ...

    <partial template="blast-results" ng-init="blast_results=results"></partial>


text: <script src="es6.min.js"></script>


text:
<?php

namespace mako\http\responses;

use \RuntimeException;

use \mako\file\FileSystem;
use \mako\http\Request;
use \mako\http\Response;

/**
 * File response.
 *
 * @author  Frederic G. Østby
 */

Class File implements \mako\http\responses\ResponseContainerInterface
{
	/**
	 * File system instance.
	 *
	 * @var \mako\file\FileSystem
	 */

	protected $fileSystem;

	/**
	 * File path.
	 *
	 * @var string
	 */

	protected $filePath;

	/**
	 * File size.
	 *
	 * @var int
	 */

	protected $fileSize;

	/**
	 * Options.
	 *
	 * @var array
	 */

	protected $options;

	/**
	 * Constructor.
	 *
	 * @access  public
	 * @param   string  $file     File path
	 * @param   array   $options  Options
	 */

	public function __construct($file, array $options = [])
	{
		$this->fileSystem = $this->getFileSystem();

		if($this->fileSystem->exists($file) === false || $this->fileSystem->isReadable($file) === false)
		{
			throw new RuntimeException(vsprintf("%s(): File [ %s ] is not readable.", [__METHOD__, $file]));
		}

		$this->filePath = $file;

		$this->fileSize = $this->fileSystem->size($file);

		$this->options = $options +
		[
			'file_name'    => basename($file),
			'disposition'  => 'attachment',
			'content_type' => $this->fileSystem->mime($file) ?: 'application/octet-stream',
			'callback'     => null,
		];
	}

	/**
	 * Returns a file system instance.
	 *
	 * @access  protected
	 * @return  \mako\file\FileSystem
	 */

	protected function getFileSystem()
	{
		return new FileSystem;
	}

	/**
	 * Calculates the content range that should be served.
	 *
	 * @access  protected
	 * @param   string       $range  Request range
	 * @return  array|false
	 */

	protected function calculateRange($range)
	{
		// Remove the "range=" part of the header value

		$range = substr($range, 6);

		// Split the range starting and ending points

		$range = explode('-', $range, 2);

		// Check that the range contains two values

		if(count($range) !== 2)
		{
			return false;
		}

		// Determine start and ending points

		$end = $range[1] === '' ? $this->fileSize - 1 : $range[1];

		if($range[0] === '')
		{
			$start = $this->fileSize - $end;
			$end   = $this->fileSize - 1;
		}
		else
		{
			$start = $range[0];
		}

		$start = (int) $start;
		$end   = (int) $end;

		// Check that the range is satisfiable

		if($start > $end || $end + 1 > $this->fileSize)
		{
			return false;
		}

		// Return the range

		return compact('start', 'end');
	}

	/**
	 * Sends the file.
	 *
	 * @access  protected
	 * @param   int        $start  Starting point
	 * @param   int        $end    Ending point
	 */

	protected function sendFile($start, $end)
	{
		// Erase output buffers and disable output buffering

		while(ob_get_level() > 0) ob_end_clean();

		// Open the file for reading

		$handle = fopen($this->filePath, 'rb');

		// Move to the correct starting position

		fseek($handle, $start);

		// Send the file contents

		$chunkSize = 4096;

		while(!feof($handle) && ($pos = ftell($handle)) <= $end && !connection_aborted())
		{
			if($pos + $chunkSize > $end)
			{
				$chunkSize = $end - $pos + 1;
			}

			echo fread($handle, $chunkSize);

			flush();
		}

		fclose($handle);
	}

	/**
	 * Sends the response.
	 *
	 * @access  public
	 * @param   \mako\http\Request   $request  Request instance
	 * @param   \mako\http\Response  $response  Response instance
	 */

	public function send(Request $request, Response $response)
	{
		// Add headers that should always be included

		$response->type($this->options['content_type']);

		$response->header('accept-ranges', 'bytes');

		$response->header('content-disposition', $this->options['disposition'] . '; filename="' . $this->options['file_name'] . '"');

		// Get the requested byte range

		$range = $request->header('range');

		if($range !== null)
		{
			$range = $this->calculateRange($range);
		}

		if($range === false)
		{
			// Not an acceptable range so we'll just send an empty response
			// along with a "requested range not satisfiable" status

			$response->status(416);

			$response->sendHeaders();
		}
		else
		{
			if($range === null)
			{
				// No range was provided by the client so we'll just fake one for the sendFile method
				// and set the content-length header value to the full file size

				$range = ['start' => 0, 'end' => $this->fileSize - 1];

				$response->header('content-length', $this->fileSize);
			}
			else
			{
				// Valid range so we'll need to tell the client which range we're sending
				// and set the content-length header value to the length of the byte range

				$response->status(206);

				$response->header('content-range', sprintf('bytes %s-%s/%s', $range['start'], $range['end'], $this->fileSize));

				$response->header('content-length', $range['end'] - $range['start'] + 1);
			}

			// Send headers and the requested byte range

			$response->sendHeaders();

			$this->sendFile($range['start'], $range['end']);

			// Execute callback if there is one

			if(!empty($this->options['callback']))
			{
				$this->options['callback']($this->filePath);
			}
		}
	}
}