]> gitweb.hamatoma.de Git - reqt/commitdiff
reditor: scrollbar sizes correct, tab expanding
authorhama <hama@siduction.net>
Tue, 23 Jun 2015 22:32:00 +0000 (00:32 +0200)
committerhama <hama@siduction.net>
Tue, 23 Jun 2015 22:32:00 +0000 (00:32 +0200)
appl/reditor/mainwindow.cpp
base/rebase.hpp
gui/ReEdit.cpp
gui/ReEdit.hpp

index 92b679e7c61cbfe066f2bac67631e0a83c7561f6..400b8f5748e44663b26a8ca87fc106ba5ba47b0c 100644 (file)
@@ -20,13 +20,12 @@ MainWindow::MainWindow(QWidget *parent) :
    ui->setupUi(this);
    ReEdit* edit = ui->widget;
 #if defined __linux__
-   m_file = new ReFile("/home/hm/lehrplan.txt", false);
+   m_file = new ReFile("/home/hm/editor.txt", false);
 #else
    m_file = new ReFile("U:\\ws_cpp\\rplqt\\Doxyfile", false);
 #endif
    edit->setLines(m_file);
    edit->setCursorLine(0);
-   edit->paragraphs().load(0, 5, edit);
    connect(ui->actionOpen, SIGNAL(triggered()), this,
       SLOT(openFile()));
 
index e1fc639b9f12080f3f52e5dc699efcde12739520..9e010bb8e0931708d4e6c1b45a54aedb7bb3de81 100644 (file)
@@ -62,6 +62,14 @@ typedef QString ReString;
 #endif
 
 #define UNUSED_VAR(var) (void) var
+inline
+int max(int a, int b){
+    return a > b ? a : b;
+}
+inline
+int min(int a, int b){
+    return a < b ? a : b;
+}
 
 #include "remodules.hpp"
 #include "base/ReByteStorage.hpp"
index 5a204329ef55a6fee104943d0c0b50480364e17b..4890ae78f590fb910fd4f5e691282b0082871d6a 100644 (file)
 #include "gui/regui.hpp"
 #include <QPaintEvent>
 
+QStringList ReEdit::m_tabStrings;
+// left arrow:
+QChar ReEdit::m_tabChar = QChar(2192);
+int ReEdit::m_tabWidth = 3;
+
 /**
  * Calculates the full line height (with gap between lines)
  *
@@ -101,14 +106,18 @@ ReEdit::ReEdit(QWidget* parent) :
             m_cursorLine(0),
             m_cursorCol(-1),
             m_cursorVisible(true),
+            m_widthEdit(0),
+            m_heightEdit(0),
             m_insertMode(true),
             m_breakLines(false),
             m_widthLineNo(50),
-            m_widthVScrollBar(0),
-            m_widthHScrollBar(0),
+            m_widthVScrollBar(20),
+            m_heightHScrollBar(20),
             m_lines(NULL),
             m_looks(),
             m_standardBrush(new QBrush(Qt::SolidPattern)),
+            m_scrollbarBrush(new QBrush(Qt::SolidPattern)),
+            m_sliderBrush(new QBrush(Qt::ConicalGradientPattern)),
             m_brushColors(),
             m_standardPen(new QPen(Qt::SolidLine)),
             m_standardFont(NULL),
@@ -128,6 +137,9 @@ ReEdit::ReEdit(QWidget* parent) :
    m_standardFont->setPixelSize(16);
    m_standardMetrics = new QFontMetrics(*m_standardFont);
    m_standardBrush->setColor(Qt::white);
+   QColor color1(214, 210, 208);
+   m_scrollbarBrush->setColor(color1);
+   m_sliderBrush->setColor(Qt::lightGray);
    memset(m_looks, 0, sizeof m_looks);
    memset(m_brushColors, 0, sizeof m_brushColors);
    m_fontColors[ReLook::FG_STANDARD] = new QColor(Qt::black);
@@ -178,6 +190,7 @@ ReEdit::ReEdit(QWidget* parent) :
    m_keyControl[Qt::Key_Delete] = EA_DEL_END_OF_LINE;
    m_keyShift[Qt::Key_Delete] = EA_DEL_BEGIN_OF_LINE;
    m_keyAlt[Qt::Key_Delete] = EA_DEL_LINE;
+   setTabStrings(3);
 }
 
 /**
@@ -228,16 +241,17 @@ QBrush* ReEdit::createBrush(ReLook::BackGround background){
 void ReEdit::paintEvent(QPaintEvent* event){
    QRect rect = event->rect();
    m_widthEdit = rect.width();
+   m_heightEdit = rect.height();
    int lineHeight = heightToFullHeight(m_standardMetrics->height());
-   int pageSize = rect.height() / lineHeight;
+   int pageSize = (rect.height() - m_heightHScrollBar) / lineHeight;
    int firstLine = m_paragraphs.firstLine();
    m_paragraphs.load(firstLine, pageSize, this);
 
    QPainter painter(this);
    ReLook* look = lookOf(ReLook::FG_STANDARD, ReLook::BG_STANDARD);
    painter.setBrush(*look->m_brush);
-   QRect editArea(rect.left() + m_widthLineNo, rect.top(), rect.right(),
-      rect.bottom());
+   QRect editArea(rect.left() + m_widthLineNo, rect.top(),
+      rect.right() - m_widthVScrollBar, rect.bottom() - m_heightHScrollBar);
    painter.drawRect(editArea);
    m_paragraphs.draw(painter, rect.top(), rect.left() + m_widthLineNo);
    int left = rect.left() + m_widthLineNo - 3;
@@ -272,8 +286,64 @@ void ReEdit::paintEvent(QPaintEvent* event){
       painter.setPen(*look->m_pen);
       painter.drawLine(x, y, x, y + lineHeight);
    }
+   int maxWidth = max(1, m_paragraphs.maxLineLength());
+   int width = (rect.width() - m_widthLineNo - m_widthVScrollBar)
+      / m_standardMetrics->width('x');
+   int maxLines = max(1, m_lines->lineCount() - pageSize);
+   drawScrollbars(painter, rect, pageSize * 100 / maxLines,
+      m_paragraphs.firstLine() * 100 / maxLines, width * 100 / maxWidth, 0);
+}
+
+void calcSliderSize(int size, int minSize, int sizePercent, int posPercent,
+   int& position, int& length){
+   if (sizePercent > 100)
+      sizePercent = 100;
+   if (posPercent > 100)
+      posPercent = 100;
+   length = size * sizePercent / 100;
+   if (length < minSize)
+      length = minSize;
+   position = (size - length) * posPercent / 100;
 }
 
+/**
+ * Draws the scrollbars.
+ *
+ * @param painter           the paint unit
+ * @param rect              the full area of the edit field
+ * @param sizeVertical      the size of the scrollbar (in %)
+ * @param posVertical       the position of the scrollbar (in %)
+ * @param sizeHorizontal    the size of the scrollbar (in %)
+ * @param posHorizontal     the position of the scrollbar (in %)
+ */
+void ReEdit::drawScrollbars(QPainter& painter, const QRect& rect,
+   int sizeVertical, int posVertical, int sizeHorizontal, int posHorizontal){
+   // We paint the vertical scrollbar:
+   painter.setBrush(*m_scrollbarBrush);
+   int x = rect.right() - m_widthVScrollBar;
+   painter.drawRect(x, rect.top(), m_widthVScrollBar,
+      rect.height() - m_heightHScrollBar);
+
+   // We paint the horizontal scrollbar:
+   painter.drawRect(rect.left() + m_widthLineNo,
+      rect.bottom() - m_heightHScrollBar,
+      rect.width() - m_widthVScrollBar - m_widthLineNo, m_heightHScrollBar);
+
+   // Slider (vertical)
+   painter.setBrush(*m_sliderBrush);
+   int sliderSize = 0;
+   int sliderPos = 0;
+   calcSliderSize(rect.height() - m_heightHScrollBar, m_heightHScrollBar,
+      sizeVertical, posVertical, sliderPos, sliderSize);
+   painter.drawRect(x + 1, rect.top() + sliderPos, m_widthVScrollBar - 2,
+      sliderSize);
+   // Slider (horizontal)
+   calcSliderSize(rect.width() - m_widthLineNo - m_widthVScrollBar,
+      m_heightHScrollBar, sizeHorizontal, posHorizontal, sliderPos, sliderSize);
+   painter.drawRect(rect.left() + m_widthLineNo + sliderPos,
+      rect.bottom() - m_heightHScrollBar + 1, sliderSize,
+      m_heightHScrollBar - 2);
+}
 /**
  * Handles the mouse click event.
  *
@@ -388,6 +458,26 @@ void ReEdit::keyPressEvent(QKeyEvent* event){
    }
    emit repaint();
 }
+/**
+ * Calculates the tabulator expanding strings.
+ *
+ * Example (tab width = 3):
+ * <pre>
+ *   "\tz" -> '   z' -> '\t' + '  '
+ *  "x\tz" -> 'x  z' -> '\t' + ' '
+ * "xy\tz" -> 'xy z' -> '\t'
+ * </pre>
+ * @param tabWidth
+ */
+void ReEdit::setTabStrings(int tabWidth){
+   m_tabWidth = tabWidth;
+   m_tabStrings.clear();
+   QString blanks;
+   blanks.fill(' ', tabWidth);
+   for (int ix = 0; ix < tabWidth - 1; ix++){
+      m_tabStrings.append(m_tabChar + blanks.mid(0, tabWidth - 1 - ix));
+   }
+}
 
 /**
  * Returns the line number of the cursor line.
@@ -530,6 +620,18 @@ void ReEdit::setLines(ReLines* lines){
    emit repaint();
 }
 
+/**
+ * Constructor.
+ */
+ReParagraphs::ReParagraphs() :
+            m_builders(),
+            m_firstLine(0),
+            m_lines(NULL),
+            m_list(),
+            m_maxLineLength(0){
+
+}
+
 /**
  * Destructor.
  */
@@ -541,6 +643,7 @@ ReParagraphs::~ReParagraphs(){
  * Makes the list empty and frees the resources.
  */
 void ReParagraphs::clear(){
+   m_maxLineLength = 0;
    for (int ix = m_list.length() - 1; ix >= 0; ix--){
       ReParagraph* current = m_list.at(ix);
       delete current;
@@ -572,12 +675,16 @@ void ReParagraphs::draw(QPainter& painter, int top, int left){
  */
 void ReParagraphs::load(int lineNo, int count, ReEdit* edit){
    clear();
+   m_maxLineLength = 0;
    m_firstLine = lineNo;
    for (int ix = lineNo; ix < lineNo + count; ix++){
       ReParagraph* para = new ReParagraph();
       m_list.append(para);
       for (int builder = 0; builder < m_builders.length(); builder++)
          m_builders.at(builder)->buildParagraph(*para, ix, edit);
+      int current = para->m_columns;
+      if (current > m_maxLineLength)
+         m_maxLineLength = current;
    }
 }
 
@@ -592,8 +699,24 @@ void ReParagraphBuilder::buildParagraph(ReParagraph& paragraph, int lineNo,
    ReEdit* edit){
    if (paragraph.length() == 0){
       const QString& text = edit->lines().lineAt(lineNo);
-      ReEditText* part = new ReEditText(text,
-         edit->lookOf(ReLook::FG_STANDARD, ReLook::BG_STANDARD));
+      ReLook* look = edit->lookOf(ReLook::FG_STANDARD, ReLook::BG_STANDARD);
+      paragraph.m_columns = 0;
+      int ixTab;
+      ReEditText* part;
+      int start = 0;
+      while ((ixTab = text.indexOf('\t', start)) >= 0){
+         if (ixTab > start){
+            part = new ReEditText(text.mid(start, ixTab - start), look);
+            paragraph.append(part);
+            paragraph.m_columns += ixTab - start;
+         }
+         paragraph.append(
+            new ReEditText(ReEdit::tabString(paragraph.m_columns), look));
+         start = ixTab + 1;
+      }
+
+      part = new ReEditText(start == 0 ? text : text.mid(start), look);
+      paragraph.m_columns += part->text().length();
       paragraph.append(part);
    }
 }
@@ -619,23 +742,18 @@ ReParagraph::~ReParagraph(){
 void ReParagraph::draw(QPainter& painter, int& top, int left){
    int x = left;
    QFontMetrics* metrics = at(0)->look()->m_metrics;
+   x += metrics->width('x') / 2;
    int height = metrics->height();
    int y = top + height - metrics->descent();
    top += heightToFullHeight(height);
    for (int ix = 0; ix < length(); ix++){
       ReEditText* current = at(ix);
-#if 0
-      QBrush& brush = *current->look()->m_brush;
-      brush.setColor(Qt::lightGray);
-      painter.setBackground(brush);
-#endif
       QFont& font = *current->look()->m_font;
       painter.setFont(font);
       QPen& pen = *current->look()->m_pen;
-      //pen.setColor(Qt::blue);
-      //QColor color1 = pen.color();
       painter.setPen(pen);
       painter.drawText(x, y, current->text());
       x += metrics->width(current->text());
    }
 }
+
index 930b1881535df00cdefbf2439f83f98c7ee5a165..80ae8e88bb4bb3fbd9fb6b7c3c14b40c06e84459 100644 (file)
@@ -130,6 +130,9 @@ public:
    virtual ~ReParagraph();
 public:
    void draw(QPainter& painter, int& top, int left);
+public:
+   // number of columns of the paragraph (length with expanded tabs).
+   int m_columns;
 };
 
 /**
@@ -160,6 +163,7 @@ public:
  */
 class ReParagraphs {
 public:
+   ReParagraphs();
    virtual ~ReParagraphs();
 public:
    /** Appends a paragraph builder to the list
@@ -206,6 +210,13 @@ public:
    QList <ReParagraph*>& list(){
       return m_list;
    }
+   /** Returns the maximal line length of all lines in the paragraph list.
+    * @return the maximal line length
+    */
+   inline
+   int maxLineLength() const{
+      return m_maxLineLength;
+   }
 
 protected:
    QList <ReParagraphBuilder*> m_builders;
@@ -213,6 +224,7 @@ protected:
    int m_firstLine;
    ReLines* m_lines;
    QList <ReParagraph*> m_list;
+   int m_maxLineLength;
 };
 
 /**
@@ -263,6 +275,8 @@ public:
 protected:
    int columnToTextIndex(int cursorCol);
    QBrush* createBrush(ReLook::BackGround background);
+   void drawScrollbars(QPainter& painter, const QRect& rect, int sizeVertical,
+      int posVertical, int sizeHorizontal, int posHorizontal);
    void ensureCursorVisible(int cursorLine = -1);
    void reposition(int firstLine);
    int textIndexToColumn(int index);
@@ -270,6 +284,15 @@ protected slots:
    void paintEvent(QPaintEvent *);
    void mousePressEvent(QMouseEvent* event);
    void keyPressEvent(QKeyEvent* event);
+public:
+   /** Returns the tabulator expanding string.
+    * @param position   the position of the tabulator (0..N-1)
+    * @return           the tabulator expanding string
+    */
+   inline static const QString& tabString(int position){
+      return m_tabStrings.at(position % m_tabWidth);
+   }
+   static void setTabStrings(int tabWidth);
 protected:
    /// the lines to display
    ReParagraphs m_paragraphs;
@@ -285,6 +308,8 @@ protected:
    bool m_cursorVisible;
    // number of pixels of the width of the edit field
    int m_widthEdit;
+   // number of pixels of the height of the edit field
+   int m_heightEdit;
    /// true: keys will be inserted at the cursor position
    bool m_insertMode;
    /// true: a file line will be displayed in multiple lines (if long enough)
@@ -294,10 +319,12 @@ protected:
    /// number of pixels for the right scroll bar
    int m_widthVScrollBar;
    /// number of pixels for the bottom scroll bar
-   int m_widthHScrollBar;
+   int m_heightHScrollBar;
    ReLines* m_lines;
    ReLook* m_looks[ReLook::BG_COUNT * ReLook::FG_COUNT];
    QBrush* m_standardBrush;
+   QBrush* m_scrollbarBrush;
+   QBrush* m_sliderBrush;
    QColor* m_brushColors[ReLook::BG_COUNT];
    QPen* m_standardPen;
    QFont* m_standardFont;
@@ -311,6 +338,10 @@ protected:
    QMap <int, EditorAction> m_keyControlShift;
    QMap <int, EditorAction> m_keyRaw;
    QMap <int, EditorAction> m_keyShift;
+protected:
+   static QStringList m_tabStrings;
+   static QChar m_tabChar;
+   static int m_tabWidth;
 };
 
 #endif // REEDITOR_HPP