org.jkiss.dbeaver.ui.controls.resultset.plaintext.PlainTextPresentation.java Source code

Java tutorial

Introduction

Here is the source code for org.jkiss.dbeaver.ui.controls.resultset.plaintext.PlainTextPresentation.java

Source

/*
 * DBeaver - Universal Database Manager
 * Copyright (C) 2010-2016 Serge Rieder (serge@jkiss.org)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (version 2)
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package org.jkiss.dbeaver.ui.controls.resultset.plaintext;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CaretEvent;
import org.eclipse.swt.custom.CaretListener;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.ui.themes.IThemeManager;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBeaverPreferences;
import org.jkiss.dbeaver.model.data.DBDAttributeBinding;
import org.jkiss.dbeaver.model.data.DBDDisplayFormat;
import org.jkiss.dbeaver.ui.StyledTextFindReplaceTarget;
import org.jkiss.dbeaver.ui.TextUtils;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.controls.resultset.*;
import org.jkiss.utils.CommonUtils;

import java.util.List;

/**
 * Empty presentation.
 * Used when RSV has no results (initially).
 */
public class PlainTextPresentation extends AbstractPresentation implements IAdaptable {

    public static final int FIRST_ROW_LINE = 2;

    private StyledText text;
    private DBDAttributeBinding curAttribute;
    private StyledTextFindReplaceTarget findReplaceTarget;
    public boolean activated;
    private Color curLineColor;

    private int[] colWidths;
    private StyleRange curLineRange;
    private int totalRows = 0;

    @Override
    public void createPresentation(@NotNull final IResultSetController controller, @NotNull Composite parent) {
        super.createPresentation(controller, parent);

        UIUtils.createHorizontalLine(parent);
        text = new StyledText(parent, SWT.READ_ONLY | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
        text.setBlockSelection(true);
        text.setCursor(parent.getDisplay().getSystemCursor(SWT.CURSOR_IBEAM));
        text.setMargins(4, 4, 4, 4);
        text.setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT));
        text.setLayoutData(new GridData(GridData.FILL_BOTH));
        text.addCaretListener(new CaretListener() {
            @Override
            public void caretMoved(CaretEvent event) {
                onCursorChange(event.caretOffset);
            }
        });

        final ScrollBar verticalBar = text.getVerticalBar();
        verticalBar.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if (verticalBar.getSelection() + verticalBar.getPageIncrement() >= verticalBar.getMaximum()) {
                    if (controller.getPreferenceStore()
                            .getBoolean(DBeaverPreferences.RESULT_SET_AUTO_FETCH_NEXT_SEGMENT)
                            && !controller.isRecordMode() && controller.isHasMoreData()) {
                        controller.readNextSegment();
                    }
                }
            }
        });
        findReplaceTarget = new StyledTextFindReplaceTarget(text);
        UIUtils.enableHostEditorKeyBindingsSupport(controller.getSite(), text);
        applyThemeSettings();

        registerContextMenu();
        trackPresentationControl();
    }

    private void applyThemeSettings() {
        IThemeManager themeManager = controller.getSite().getWorkbenchWindow().getWorkbench().getThemeManager();
        curLineColor = themeManager.getCurrentTheme().getColorRegistry()
                .get(ThemeConstants.COLOR_SQL_RESULT_CELL_ODD_BACK);
    }

    private void onCursorChange(int offset) {
        ResultSetModel model = controller.getModel();

        int lineNum = text.getLineAtOffset(offset);
        int lineOffset = text.getOffsetAtLine(lineNum);
        int horizontalOffset = offset - lineOffset;

        int lineCount = text.getLineCount();

        int rowNum = lineNum - FIRST_ROW_LINE; //First 2 lines is header
        if (controller.isRecordMode()) {
            if (rowNum < 0) {
                rowNum = 0;
            }
            if (rowNum >= 0 && rowNum < model.getVisibleAttributeCount()) {
                curAttribute = model.getVisibleAttribute(rowNum);
            }
        } else {
            int colNum = 0;
            int horOffsetBegin = 0, horOffsetEnd = 0;
            for (int i = 0; i < colWidths.length; i++) {
                horOffsetBegin = horOffsetEnd;
                horOffsetEnd += colWidths[i] + 1;
                if (horizontalOffset < horOffsetEnd) {
                    colNum = i;
                    break;
                }
            }
            if (rowNum < 0 && model.getRowCount() > 0) {
                rowNum = 0;
            }
            if (rowNum >= 0 && rowNum < model.getRowCount() && colNum >= 0
                    && colNum < model.getVisibleAttributeCount()) {
                controller.setCurrentRow(model.getRow(rowNum));
                curAttribute = model.getVisibleAttribute(colNum);
            }
            controller.updateEditControls();

            {
                // Highlight row
                if (curLineRange == null || curLineRange.start != lineOffset + horOffsetBegin) {
                    curLineRange = new StyleRange(lineOffset + horOffsetBegin, horOffsetEnd - horOffsetBegin - 1,
                            null, curLineColor);
                    text.getDisplay().asyncExec(new Runnable() {
                        @Override
                        public void run() {
                            text.setStyleRanges(new StyleRange[] { curLineRange });
                        }
                    });
                }
            }

            if (lineNum == lineCount - 1 && controller.isHasMoreData() && controller.getPreferenceStore()
                    .getBoolean(DBeaverPreferences.RESULT_SET_AUTO_FETCH_NEXT_SEGMENT)) {
                controller.readNextSegment();
            }
        }
    }

    @Override
    public Control getControl() {
        return text;
    }

    @Override
    public void refreshData(boolean refreshMetadata, boolean append) {
        if (controller.isRecordMode()) {
            printRecord();
        } else {
            printGrid(append);
        }
    }

    private void printGrid(boolean append) {
        int maxColumnSize = getController().getPreferenceStore()
                .getInt(DBeaverPreferences.RESULT_TEXT_MAX_COLUMN_SIZE);
        StringBuilder grid = new StringBuilder(512);
        ResultSetModel model = controller.getModel();
        List<DBDAttributeBinding> attrs = model.getVisibleAttributes();

        List<ResultSetRow> allRows = model.getAllRows();
        if (colWidths == null) {
            // Calculate column widths
            colWidths = new int[attrs.size()];

            for (int i = 0; i < attrs.size(); i++) {
                DBDAttributeBinding attr = attrs.get(i);
                colWidths[i] = getAttributeName(attr).length();
                for (ResultSetRow row : allRows) {
                    String displayString = getCellString(model, attr, row);
                    colWidths[i] = Math.max(colWidths[i], displayString.length());
                }
            }
            for (int i = 0; i < colWidths.length; i++) {
                colWidths[i]++;
                if (colWidths[i] > maxColumnSize) {
                    colWidths[i] = maxColumnSize;
                }
            }
        }

        if (!append) {
            // Print header
            for (int i = 0; i < attrs.size(); i++) {
                DBDAttributeBinding attr = attrs.get(i);
                String attrName = getAttributeName(attr);
                grid.append(attrName);
                for (int k = colWidths[i] - attrName.length(); k > 0; k--) {
                    grid.append(" ");
                }
                grid.append("|");
            }
            grid.append("\n");

            // Print divider
            // Print header
            for (int i = 0; i < attrs.size(); i++) {
                for (int k = colWidths[i]; k > 0; k--) {
                    grid.append("-");
                }
                grid.append("|");
            }
            grid.append("\n");
        }

        // Print rows
        int firstRow = append ? totalRows : 0;
        if (append) {
            grid.append("\n");
        }
        for (int i = firstRow; i < allRows.size(); i++) {
            ResultSetRow row = allRows.get(i);
            for (int k = 0; k < attrs.size(); k++) {
                DBDAttributeBinding attr = attrs.get(k);
                String displayString = getCellString(model, attr, row);
                if (displayString.length() >= colWidths[k] - 1) {
                    displayString = CommonUtils.truncateString(displayString, colWidths[k] - 1);
                }
                grid.append(displayString);
                for (int j = colWidths[k] - displayString.length(); j > 0; j--) {
                    grid.append(" ");
                }
                grid.append("|");
            }
            grid.append("\n");
        }
        grid.setLength(grid.length() - 1); // cut last line feed

        if (append) {
            text.append(grid.toString());
        } else {
            text.setText(grid.toString());
        }

        totalRows = allRows.size();
    }

    private static String getAttributeName(DBDAttributeBinding attr) {
        if (CommonUtils.isEmpty(attr.getLabel())) {
            return attr.getName();
        } else {
            return attr.getLabel();
        }
    }

    private String getCellString(ResultSetModel model, DBDAttributeBinding attr, ResultSetRow row) {
        String displayString = attr.getValueHandler().getValueDisplayString(attr, model.getCellValue(attr, row),
                DBDDisplayFormat.EDIT);
        return TextUtils.getSingleLineString(displayString);
    }

    private void printRecord() {
        StringBuilder grid = new StringBuilder(512);
        ResultSetModel model = controller.getModel();
        List<DBDAttributeBinding> attrs = model.getVisibleAttributes();
        String[] values = new String[attrs.size()];
        ResultSetRow currentRow = controller.getCurrentRow();

        // Calculate column widths
        int nameWidth = 4, valueWidth = 5;
        for (int i = 0; i < attrs.size(); i++) {
            DBDAttributeBinding attr = attrs.get(i);
            nameWidth = Math.max(nameWidth, getAttributeName(attr).length());
            values[i] = attr.getValueHandler().getValueDisplayString(attr, model.getCellValue(attr, currentRow),
                    DBDDisplayFormat.EDIT);
            valueWidth = Math.max(valueWidth, values[i].length());
        }

        // Header
        grid.append("Name");
        for (int j = nameWidth - 4; j > 0; j--) {
            grid.append(" ");
        }
        grid.append("|Value\n");
        for (int j = 0; j < nameWidth; j++)
            grid.append("-");
        grid.append("|");
        for (int j = 0; j < valueWidth; j++)
            grid.append("-");
        grid.append("\n");

        // Values
        for (int i = 0; i < attrs.size(); i++) {
            DBDAttributeBinding attr = attrs.get(i);
            String name = getAttributeName(attr);
            grid.append(name);
            for (int j = nameWidth - name.length(); j > 0; j--) {
                grid.append(" ");
            }
            grid.append("|");
            grid.append(values[i]);
            grid.append("\n");
        }
        grid.setLength(grid.length() - 1); // cut last line feed
        text.setText(grid.toString());
    }

    @Override
    public void formatData(boolean refreshData) {
        //controller.refreshData(null);
    }

    @Override
    public void clearMetaData() {
        colWidths = null;
        curLineRange = null;
        totalRows = 0;
    }

    @Override
    public void updateValueView() {

    }

    @Override
    public void fillToolbar(@NotNull IToolBarManager toolBar) {

    }

    @Override
    public void fillMenu(@NotNull IMenuManager menu) {

    }

    @Override
    public void changeMode(boolean recordMode) {

    }

    @Override
    public void scrollToRow(@NotNull RowPosition position) {
        if (controller.isRecordMode()) {
            super.scrollToRow(position);
        } else {
            int caretOffset = text.getCaretOffset();
            if (caretOffset < 0)
                caretOffset = 0;
            int lineNum = text.getLineAtOffset(caretOffset);
            if (lineNum < FIRST_ROW_LINE) {
                lineNum = FIRST_ROW_LINE;
            }
            int lineOffset = text.getOffsetAtLine(lineNum);
            int xOffset = caretOffset - lineOffset;
            int totalLines = text.getLineCount();
            switch (position) {
            case FIRST:
                lineNum = FIRST_ROW_LINE;
                break;
            case PREVIOUS:
                lineNum--;
                break;
            case NEXT:
                lineNum++;
                break;
            case LAST:
                lineNum = totalLines - 1;
                break;
            case CURRENT:
                lineNum = controller.getCurrentRow().getVisualNumber() + FIRST_ROW_LINE;
                break;
            }
            if (lineNum < FIRST_ROW_LINE || lineNum >= totalLines) {
                return;
            }
            int newOffset = text.getOffsetAtLine(lineNum);
            newOffset += xOffset;
            text.setCaretOffset(newOffset);
            //text.setSelection(newOffset, 0);
            text.showSelection();
        }
    }

    @Nullable
    @Override
    public DBDAttributeBinding getCurrentAttribute() {
        return curAttribute;
    }

    @Nullable
    @Override
    public String copySelectionToString(boolean copyHeader, boolean copyRowNumbers, boolean cut, String delimiter,
            DBDDisplayFormat format) {
        return text.getSelectionText();
    }

    @Override
    public Object getAdapter(Class adapter) {
        if (adapter == IFindReplaceTarget.class) {
            return findReplaceTarget;
        }
        return null;
    }
}