/****************************************************************************
**
** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
**
** This file is part of Qt Jambi.
**
** ** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.

**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/


package com.trolltech.examples;

import com.trolltech.qt.*;
import com.trolltech.qt.core.*;
import com.trolltech.qt.gui.*;

import java.util.*;

@QtJambiExample(name = "Code Editor")
public class CodeEditor extends QPlainTextEdit
{
    
//![constructor]
    public CodeEditor()
    {
        lineNumberArea = new LineNumberArea(this);

        blockCountChanged.connect(this, "updateLineNumberAreaWidth(Integer)");
        updateRequest.connect(this, "updateLineNumberArea(QRect,Integer)");
        cursorPositionChanged.connect(this, "highlightCurrentLine()");

        updateLineNumberAreaWidth(0);
        highlightCurrentLine();

        setWindowTitle("Code Editor Example");
        setWindowIcon(new QIcon("classpath:com/trolltech/images/qt-logo.png"));
    }
//![constructor]

//![extraAreaWidth]
    public int lineNumberAreaWidth()
    {
        int digits = 1;
        int max = Math.max(1, blockCount());
        while (max >= 10) {
            max /= 10;
            ++digits;
        }

        int space = 3 + fontMetrics().width('9') * digits;

        return space;
    }
//![extraAreaWidth]

//![slotUpdateExtraAreaWidth]
    public void updateLineNumberAreaWidth(Integer newBlockCount)
    {
        setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
    }
//![slotUpdateExtraAreaWidth]

//![slotUpdateRequest]
    public void updateLineNumberArea(QRect rect, Integer dy)
    {
        if (dy > 0)
            lineNumberArea.scroll(0, dy);
        else
            lineNumberArea.update(0, rect.y(), lineNumberArea.width(),
                                  rect.height());

        if (rect.contains(viewport().rect()))
            updateLineNumberAreaWidth(0);
    }
//![slotUpdateRequest]

//![resizeEvent]
    @Override
    protected void resizeEvent(QResizeEvent e)
    {
        super.resizeEvent(e);

        QRect cr = contentsRect();
        lineNumberArea.setGeometry(new QRect(cr.left(), cr.top(),
                                   lineNumberAreaWidth(), cr.height()));
    }
//![resizeEvent]

//![cursorPositionChanged]
    private void highlightCurrentLine()
    {
        List<QTextEdit_ExtraSelection> extraSelections =
            new Vector<QTextEdit_ExtraSelection>();

        if (!isReadOnly()) {
            QTextEdit_ExtraSelection selection =
                new QTextEdit_ExtraSelection();
            
            QColor lineColor = QColor.yellow.lighter(160);

            QTextCharFormat format = selection.format();
            format.setBackground(new QBrush(lineColor));
            format.setProperty(QTextFormat.Property.FullWidthSelection.value(), new Boolean(true));
            selection.setFormat(format);
            QTextCursor cursor = textCursor();
            cursor.clearSelection();
            selection.setCursor(cursor);
            extraSelections.add(selection);
        }

        setExtraSelections(extraSelections);
    }
//![cursorPositionChanged]

//![extraAreaPaintEvent_0]
    public void lineNumberAreaPaintEvent(QPaintEvent event)
    {
        QPainter painter = new QPainter(lineNumberArea);
        painter.setPen(new QPen(QColor.black));
        painter.fillRect(event.rect(), new QBrush(QColor.lightGray));

//![extraAreaPaintEvent_0]

//![extraAreaPaintEvent_1]
        QTextBlock block = firstVisibleBlock();
        int blockNumber = block.blockNumber();
        int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
        int bottom = top + (int) blockBoundingRect(block).height();
//![extraAreaPaintEvent_1]

//![extraAreaPaintEvent_2]
        while (block.isValid() && top <= event.rect().bottom()) {
            if (block.isVisible() && bottom >= event.rect().top()) {
                String number = String.valueOf(blockNumber + 1);
                painter.drawText(0, top, lineNumberArea.width(), fontMetrics().height(),
                                Qt.AlignmentFlag.AlignRight.value(), number);
            }

            block = block.next();
            top = bottom;
            bottom = top + (int) blockBoundingRect(block).height();
            ++blockNumber;
        }
    } 
//![extraAreaPaintEvent_2]

//![extraarea]
    private static class LineNumberArea extends QWidget
    {
        public LineNumberArea(CodeEditor editor)
        {
            codeEditor = editor;
            setParent(codeEditor);
        }

        @Override
        public QSize sizeHint()
        {
            return new QSize(codeEditor.lineNumberAreaWidth(), 0);
        }

        @Override
        protected void paintEvent(QPaintEvent event)
        {
            codeEditor.lineNumberAreaPaintEvent(event);
        }

        private CodeEditor codeEditor;
    }
//![extraarea]

    private LineNumberArea lineNumberArea;

    public static void main(String args[])
    {
        QApplication.initialize(args);

        new CodeEditor().show();

        QApplication.exec();
    }
}
