diff --git a/widgets/rendererWidget/TextBrowserWidget.cc b/widgets/rendererWidget/TextBrowserWidget.cc
new file mode 100644
index 0000000000000000000000000000000000000000..18c2e2d353a26463429120f6418afb4a102cdf74
--- /dev/null
+++ b/widgets/rendererWidget/TextBrowserWidget.cc
@@ -0,0 +1,379 @@
+
+/*===========================================================================*\
+* *
+* OpenFlipper *
+* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
+* www.openflipper.org *
+* *
+*--------------------------------------------------------------------------- *
+* This file is part of OpenFlipper. *
+* *
+* OpenFlipper is free software: you can redistribute it and/or modify *
+* it under the terms of the GNU Lesser General Public License as *
+* published by the Free Software Foundation, either version 3 of *
+* the License, or (at your option) any later version with the *
+* following exceptions: *
+* *
+* If other files instantiate templates or use macros *
+* or inline functions from this file, or you compile this file and *
+* link it with other files to produce an executable, this file does *
+* not by itself cause the resulting executable to be covered by the *
+* GNU Lesser General Public License. This exception does not however *
+* invalidate any other reasons why the executable file might be *
+* covered by the GNU Lesser General Public License. *
+* *
+* OpenFlipper 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 Lesser General Public License for more details. *
+* *
+* You should have received a copy of the GNU LesserGeneral Public *
+* License along with OpenFlipper. If not, *
+* see . *
+* *
+\*===========================================================================*/
+
+/*===========================================================================*\
+* *
+* $Revision: 17080 $ *
+* $LastChangedBy: moeller $ *
+* $Date: 2013-07-19 12:58:31 +0200 (Fri, 19 Jul 2013) $ *
+* *
+\*===========================================================================*/
+
+
+#if QT_VERSION >= 0x050000
+ #include
+#else
+ #include
+#endif
+
+#include "TextBrowserWidget.hh"
+
+#include
+
+QString const TextBrowserWidget::startRenderObjectTag_ = "name:";
+QString const TextBrowserWidget::startVertexShaderTag_ = "--vertex-shader--";
+QString const TextBrowserWidget::endVertexShaderTag_ = "--end-vertex-shader--";
+QString const TextBrowserWidget::startGeometryShaderTag_ = "--geometry-shader--";
+QString const TextBrowserWidget::endGeometryShaderTag_ = "--end-geometry-shader--";
+QString const TextBrowserWidget::startFragmentShaderTag_ = "--fragment-shader--";
+QString const TextBrowserWidget::endFragmentShaderTag_ = "--end-fragment-shader--";
+
+
+TextBrowserWidget::TextBrowserWidget(QWidget *parent) : QPlainTextEdit(parent) {
+ sideArea_ = new TextBrowserSideArea(this);
+ updateTextBrowserSideAreaWidth();
+
+ connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateTextBrowserSideAreaWidth()));
+ connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateFolds()));
+ connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateTextBrowserSideArea(QRect,int)));
+
+ setReadOnly(true);
+}
+
+
+
+int TextBrowserWidget::sideAreaWidth() {
+ int digits = 1;
+ int max = qMax(1, blockCount());
+ while (max >= 10) {
+ max /= 10;
+ ++digits;
+ }
+
+ int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
+
+ return space;
+}
+
+
+
+void TextBrowserWidget::updateTextBrowserSideAreaWidth() {
+ setViewportMargins(sideAreaWidth(), 0, 0, 0);
+}
+
+void TextBrowserWidget::updateTextBrowserSideArea(const QRect &rect, int dy) {
+ if (dy)
+ sideArea_->scroll(0, dy);
+ else
+ sideArea_->update(0, rect.y(), sideArea_->width(), rect.height());
+
+ if (rect.contains(viewport()->rect()))
+ updateTextBrowserSideAreaWidth();
+}
+
+
+
+void TextBrowserWidget::resizeEvent(QResizeEvent *e) {
+ QPlainTextEdit::resizeEvent(e);
+
+ QRect cr = contentsRect();
+ sideArea_->setGeometry(QRect(cr.left(), cr.top(), sideAreaWidth(), cr.height()));
+}
+
+void TextBrowserWidget::sideAreaPaintEvent(QPaintEvent *event) {
+
+ QPainter painter(sideArea_);
+ painter.fillRect(event->rect(), Qt::lightGray);
+ painter.setPen(Qt::black);
+
+ QTextBlock block = firstVisibleBlock();
+
+ int blockNumber = block.blockNumber();
+ int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
+ int bottom = top + (int) blockBoundingRect(block).height();
+
+ Fold found_fold;
+ while (block.isValid() && top <= event->rect().bottom()) {
+ if (block.isVisible() && bottom >= event->rect().top()) {
+ if (getFold(block.position(), found_fold)) {
+ if (found_fold.type == SHADER) {
+ int fold_first_block = document()->findBlock(found_fold.start).blockNumber();
+ QString text = block.text();
+ // only draw line numbers on actual shader code
+ if (text.contains(TextBrowserWidget::startVertexShaderTag_) ||
+ text.contains(TextBrowserWidget::endVertexShaderTag_) ||
+ text.contains(TextBrowserWidget::startGeometryShaderTag_) ||
+ text.contains(TextBrowserWidget::endGeometryShaderTag_) ||
+ text.contains(TextBrowserWidget::startFragmentShaderTag_) ||
+ text.contains(TextBrowserWidget::endFragmentShaderTag_)) {
+ if (found_fold.folded)
+ painter.drawText(0, top, sideArea_->width(), fontMetrics().height(),Qt::AlignRight, "+");
+ else
+ painter.drawText(0, top, sideArea_->width(), fontMetrics().height(),Qt::AlignRight, "-");
+ } else {
+ QString number = QString::number(blockNumber - fold_first_block);
+ painter.drawText(0, top, sideArea_->width(), fontMetrics().height(),Qt::AlignRight, number);
+ }
+ } else {
+ if (found_fold.folded)
+ painter.drawText(0, top, sideArea_->width(), fontMetrics().height(),Qt::AlignRight, "+");
+ else
+ painter.drawText(0, top, sideArea_->width(), fontMetrics().height(),Qt::AlignRight, "-");
+ }
+ } else
+ painter.drawText(0, top, sideArea_->width(), fontMetrics().height(),Qt::AlignRight, " ");
+ }
+
+ block = block.next();
+ top = bottom;
+ bottom = top + (int) blockBoundingRect(block).height();
+ ++blockNumber;
+ }
+}
+
+bool TextBrowserWidget::getFold(int _position, Fold& _fold) {
+ std::map::iterator it = blockPosToFold_.find(_position);
+ if (it != blockPosToFold_.end()) {
+ _fold = folds_[it->second];
+ return true;
+ } else
+ return false;
+}
+
+void TextBrowserWidget::mouseDoubleClickEvent(QMouseEvent* e) {
+ QTextBlock block = firstVisibleBlock();
+ int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
+ int bottom = top + (int) blockBoundingRect(block).height();
+ const int y = e->y();
+ // find the block that was clicked and toggle the folding
+ while (block.isValid()) {
+ if (top <= y && y <= bottom) {
+ toggleFold(block.position());
+ break;
+ }
+
+ block = block.next();
+ top = bottom;
+ bottom = top + (int) blockBoundingRect(block).height();
+ }
+}
+
+void TextBrowserWidget::foldAll() {
+ for (std::vector::iterator it = folds_.begin(); it != folds_.end(); ++it) {
+ fold(*it);
+ }
+}
+
+void TextBrowserWidget::unfoldAll() {
+ for (std::vector::iterator it = folds_.begin(); it != folds_.end(); ++it) {
+ unfold(*it);
+ }
+}
+
+void TextBrowserWidget::fold(Fold& _fold) {
+ if (_fold.folded)
+ return;
+
+ QTextBlock startBlock = document()->findBlock(_fold.start);
+ QTextBlock endBlock = document()->findBlock(_fold.end);
+
+ startBlock = startBlock.next();
+ while (startBlock.isValid() && startBlock != endBlock) {
+ startBlock.setVisible(false);
+ startBlock = startBlock.next();
+ }
+ if (_fold.type == RENDEROBJECT)
+ endBlock.setVisible(false);
+
+ _fold.folded = true;
+ document()->markContentsDirty(_fold.start, _fold.end - _fold.start);
+}
+
+void TextBrowserWidget::unfold(Fold& _fold) {
+ if (!_fold.folded)
+ return;
+
+ QTextBlock startBlock = document()->findBlock(_fold.start);
+ QTextBlock endBlock = document()->findBlock(_fold.end);
+
+ startBlock = startBlock.next();
+ while (startBlock.isValid() && startBlock != endBlock) {
+ startBlock.setVisible(true);
+ startBlock = startBlock.next();
+ }
+ if (_fold.type == RENDEROBJECT)
+ endBlock.setVisible(true);
+
+ _fold.folded = false;
+ document()->markContentsDirty(_fold.start, _fold.end-_fold.start);
+}
+
+void TextBrowserWidget::toggleFold(int _position) {
+ for (std::vector::iterator it = folds_.begin(); it != folds_.end(); ++it) {
+ if (it->contains(_position)) {
+ if (it->folded)
+ unfold(*it);
+ else
+ fold(*it);
+
+ break;
+ }
+ }
+}
+
+void TextBrowserWidget::updateFolds() {
+ folds_.clear();
+
+ // search for all vertex shader
+ QTextCursor startCursor = document()->find(TextBrowserWidget::startVertexShaderTag_, 0, QTextDocument::FindWholeWords);
+ QTextCursor endCursor = document()->find(TextBrowserWidget::endVertexShaderTag_, 0, QTextDocument::FindWholeWords);
+
+ while (!startCursor.isNull() && !endCursor.isNull()) {
+ startCursor.movePosition(QTextCursor::StartOfLine);
+ endCursor.movePosition(QTextCursor::EndOfLine);
+ folds_.push_back(Fold(startCursor.position(),endCursor.position(),SHADER));
+
+ // map block position to fold
+ int startPos = startCursor.position();
+ const int endPos = endCursor.position();
+ for (; startPos < endPos; ++startPos) {
+ QTextBlock block = document()->findBlock(startPos);
+ blockPosToFold_[block.position()] = folds_.size() - 1;
+ }
+
+ bool moved = startCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+ moved = endCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+
+ startCursor = document()->find(TextBrowserWidget::startVertexShaderTag_, startCursor, QTextDocument::FindWholeWords);
+ endCursor = document()->find(TextBrowserWidget::endVertexShaderTag_, endCursor, QTextDocument::FindWholeWords);
+ }
+
+ // search for all geometry shader
+ startCursor = document()->find(TextBrowserWidget::startGeometryShaderTag_, 0, QTextDocument::FindWholeWords);
+ endCursor = document()->find(TextBrowserWidget::endGeometryShaderTag_, 0, QTextDocument::FindWholeWords);
+
+ while (!startCursor.isNull() && !endCursor.isNull()) {
+ startCursor.movePosition(QTextCursor::StartOfLine);
+ endCursor.movePosition(QTextCursor::EndOfLine);
+ folds_.push_back(Fold(startCursor.position(),endCursor.position(),SHADER));
+
+ // map block position to fold
+ int startPos = startCursor.position();
+ const int endPos = endCursor.position();
+ for (; startPos < endPos; ++startPos) {
+ QTextBlock block = document()->findBlock(startPos);
+ blockPosToFold_[block.position()] = folds_.size() - 1;
+ }
+
+ bool moved = startCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+ moved = endCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+
+ startCursor = document()->find(TextBrowserWidget::startGeometryShaderTag_, startCursor, QTextDocument::FindWholeWords);
+ endCursor = document()->find(TextBrowserWidget::endGeometryShaderTag_, endCursor, QTextDocument::FindWholeWords);
+ }
+
+ // search for all fragment shader
+ startCursor = document()->find(TextBrowserWidget::startFragmentShaderTag_, 0, QTextDocument::FindWholeWords);
+ endCursor = document()->find(TextBrowserWidget::endFragmentShaderTag_, 0, QTextDocument::FindWholeWords);
+
+ while (!startCursor.isNull() && !endCursor.isNull()) {
+ startCursor.movePosition(QTextCursor::StartOfLine);
+ endCursor.movePosition(QTextCursor::EndOfLine);
+ folds_.push_back(Fold(startCursor.position(),endCursor.position(),SHADER));
+
+ // map block position to fold
+ int startPos = startCursor.position();
+ const int endPos = endCursor.position();
+ for (; startPos < endPos; ++startPos) {
+ QTextBlock block = document()->findBlock(startPos);
+ blockPosToFold_[block.position()] = folds_.size() - 1;
+ }
+
+ bool moved = startCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+ moved = endCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+
+ startCursor = document()->find(TextBrowserWidget::startFragmentShaderTag_, startCursor, QTextDocument::FindWholeWords);
+ endCursor = document()->find(TextBrowserWidget::endFragmentShaderTag_, endCursor, QTextDocument::FindWholeWords);
+ }
+
+ // search for all render objects
+ startCursor = document()->find(TextBrowserWidget::startRenderObjectTag_, 0, QTextDocument::FindWholeWords);
+ endCursor = document()->find(TextBrowserWidget::startVertexShaderTag_, 0, QTextDocument::FindWholeWords);
+
+ while (!startCursor.isNull() && !endCursor.isNull()) {
+ startCursor.movePosition(QTextCursor::StartOfLine);
+ // vertex shader does not belong to this fold
+ endCursor.movePosition(QTextCursor::Up);
+ endCursor.movePosition(QTextCursor::EndOfLine);
+ folds_.push_back(Fold(startCursor.position(),endCursor.position(),RENDEROBJECT));
+
+ // map block position to fold
+ int startPos = startCursor.position();
+ const int endPos = endCursor.position();
+ for (; startPos < endPos; ++startPos) {
+ QTextBlock block = document()->findBlock(startPos);
+ blockPosToFold_[block.position()] = folds_.size() - 1;
+ }
+
+ bool moved = startCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+ // skip to after the vertex shader starts
+ moved = endCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+ moved = endCursor.movePosition(QTextCursor::Down);
+ if (!moved)
+ break;
+
+ startCursor = document()->find(TextBrowserWidget::startRenderObjectTag_, startCursor, QTextDocument::FindWholeWords);
+ endCursor = document()->find(TextBrowserWidget::startVertexShaderTag_, endCursor, QTextDocument::FindWholeWords);
+ }
+
+ // fold shader blocks
+ foldAll();
+}
diff --git a/widgets/rendererWidget/TextBrowserWidget.hh b/widgets/rendererWidget/TextBrowserWidget.hh
new file mode 100644
index 0000000000000000000000000000000000000000..0f4e3199a7d973095e2576bdde09d2fd1910c9af
--- /dev/null
+++ b/widgets/rendererWidget/TextBrowserWidget.hh
@@ -0,0 +1,157 @@
+/*===========================================================================*\
+* *
+* OpenFlipper *
+* Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen *
+* www.openflipper.org *
+* *
+*--------------------------------------------------------------------------- *
+* This file is part of OpenFlipper. *
+* *
+* OpenFlipper is free software: you can redistribute it and/or modify *
+* it under the terms of the GNU Lesser General Public License as *
+* published by the Free Software Foundation, either version 3 of *
+* the License, or (at your option) any later version with the *
+* following exceptions: *
+* *
+* If other files instantiate templates or use macros *
+* or inline functions from this file, or you compile this file and *
+* link it with other files to produce an executable, this file does *
+* not by itself cause the resulting executable to be covered by the *
+* GNU Lesser General Public License. This exception does not however *
+* invalidate any other reasons why the executable file might be *
+* covered by the GNU Lesser General Public License. *
+* *
+* OpenFlipper 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 Lesser General Public License for more details. *
+* *
+* You should have received a copy of the GNU LesserGeneral Public *
+* License along with OpenFlipper. If not, *
+* see . *
+* *
+\*===========================================================================*/
+
+/*===========================================================================*\
+* *
+* $Revision: 12438 $ *
+* $LastChangedBy: moebius $ *
+* $Date: 2011-09-22 17:16:17 +0200 (Thu, 22 Sep 2011) $ *
+* *
+\*===========================================================================*/
+
+#ifndef TEXTBROWSERWIDGET_HH
+#define TEXTBROWSERWIDGET_HH
+
+#include
+#include
+
+#include
+
+class TextBrowserSideArea;
+
+
+class TextBrowserWidget : public QPlainTextEdit
+{
+ Q_OBJECT
+
+ private:
+ enum FoldType {
+ SHADER,
+ RENDEROBJECT
+ };
+
+ struct Fold {
+ Fold() :
+ start(-1),
+ end(-1),
+ folded(false),
+ type(SHADER)
+ {}
+
+ Fold(int _start, int _end, FoldType _type) :
+ start(_start),
+ end(_end),
+ folded(false),
+ type(_type)
+ {}
+
+ bool contains (int n) const {
+ return (start <= n) && (n <= end);
+ }
+
+ // start positition in the document
+ int start;
+ // end positition in the document
+ int end;
+ bool folded;
+ FoldType type;
+ };
+
+
+ public:
+ TextBrowserWidget(QWidget *parent = 0);
+
+ void sideAreaPaintEvent(QPaintEvent *event);
+ int sideAreaWidth();
+
+ protected:
+ void resizeEvent(QResizeEvent *event);
+ virtual void mouseDoubleClickEvent(QMouseEvent* e);
+
+ private slots:
+ void updateTextBrowserSideAreaWidth();
+ void updateTextBrowserSideArea(const QRect &, int);
+ void foldAll();
+ void unfoldAll();
+ void fold(Fold& _fold);
+ void unfold(Fold& _fold);
+ void toggleFold(int _position);
+ void updateFolds();
+ /** \brief get the _fold corresponding to the document _position
+ * @param _position position in the document
+ * @param _fold fold in folds_ at the position if found
+ *
+ * \return true if fold was found (otherwise false is returned)
+ */
+ bool getFold(int _position, Fold& _fold);
+
+ private:
+ TextBrowserSideArea* sideArea_;
+ static QString const startRenderObjectTag_;
+ static QString const startVertexShaderTag_;
+ static QString const endVertexShaderTag_;
+ static QString const startGeometryShaderTag_;
+ static QString const endGeometryShaderTag_;
+ static QString const startFragmentShaderTag_;
+ static QString const endFragmentShaderTag_;
+
+ std::vector folds_;
+ /// maps positions in the document to indices in folds_
+ std::map blockPosToFold_;
+};
+
+
+class TextBrowserSideArea : public QWidget
+{
+ public:
+ TextBrowserSideArea(TextBrowserWidget* _textBrowser) :
+ QWidget(_textBrowser),
+ textBrowser_(_textBrowser)
+ {}
+
+ QSize sizeHint() const {
+ return QSize(textBrowser_->sideAreaWidth(), 0);
+ }
+
+ protected:
+ void paintEvent(QPaintEvent *event) {
+ textBrowser_->sideAreaPaintEvent(event);
+ }
+
+ private:
+ TextBrowserWidget* textBrowser_;
+};
+
+
+#endif // TEXTBROWSERWIDGET_HH
diff --git a/widgets/rendererWidget/rendererObjectWidget.cc b/widgets/rendererWidget/rendererObjectWidget.cc
index 7fab1f8408abf43be1a8dd8834fbdf70ba2f6bdc..a0aa833e1a1b741baaf532570cc2b938c66e4ea1 100644
--- a/widgets/rendererWidget/rendererObjectWidget.cc
+++ b/widgets/rendererWidget/rendererObjectWidget.cc
@@ -42,7 +42,7 @@
#include "rendererObjectWidget.hh"
-#if QT_VERSION >= 0x050000
+#if QT_VERSION >= 0x050000
#include
#else
#include
@@ -57,7 +57,8 @@
RendererObjectWidget::RendererObjectWidget(QWidget *parent)
: QDialog(parent),
- highlighter_(0)
+ highlighter_(0),
+ textBrowser_(0)
{
setupUi(this);
@@ -68,7 +69,10 @@ RendererObjectWidget::RendererObjectWidget(QWidget *parent)
closeButton->setIcon( QIcon(iconPath + "window-close.png"));
- highlighter_ = new RenderObjectHighlighter( textBrowser->document() );
+ textBrowser_ = new TextBrowserWidget(this);
+ textBrowserLayout->addWidget(textBrowser_);
+
+ highlighter_ = new RenderObjectHighlighter( textBrowser_->document() );
connect(showShadersBox,SIGNAL(clicked()),this,SLOT(update()));
}
@@ -88,22 +92,20 @@ void RendererObjectWidget::update()
{
RendererInfo* renderer = renderManager().active(PluginFunctions::activeExaminer());
- textBrowser->clear();
+ textBrowser_->clear();
if ( renderer ) {
- textBrowser->insertPlainText(tr("Current renderer: ") + renderer->name +"\n");
- textBrowser->insertPlainText(tr("Description: ") + renderer->description +"\n");
- textBrowser->insertPlainText(tr("Version: ") + renderer->version + "\n" );
- textBrowser->insertPlainText("\n" );
+ textBrowser_->insertPlainText(tr("Current renderer: ") + renderer->name +"\n");
+ textBrowser_->insertPlainText(tr("Description: ") + renderer->description +"\n");
+ textBrowser_->insertPlainText(tr("Version: ") + renderer->version + "\n" );
+ textBrowser_->insertPlainText("\n" );
//TODO: Flag for shader output activate/deactivate
if ( renderManager().activeId(PluginFunctions::activeExaminer()) != 0 )
- textBrowser->insertPlainText(renderer->plugin->renderObjectsInfo(showShadersBox->isChecked()));
+ textBrowser_->insertPlainText(renderer->plugin->renderObjectsInfo(showShadersBox->isChecked()));
} else {
- textBrowser->setText("Unable to get renderer!");
+ textBrowser_->insertPlainText("Unable to get renderer!");
}
-
-
}
diff --git a/widgets/rendererWidget/rendererObjectWidget.hh b/widgets/rendererWidget/rendererObjectWidget.hh
index d10667957800dd1188401555320dd7a105ba40b5..eaab5749cee300d06fb75260a0fde3f4f55b395d 100644
--- a/widgets/rendererWidget/rendererObjectWidget.hh
+++ b/widgets/rendererWidget/rendererObjectWidget.hh
@@ -45,6 +45,7 @@
#include
#include "renderObjectHighLighter.hh"
+#include "TextBrowserWidget.hh"
class RendererObjectWidget : public QDialog, public Ui::RendererObjectWidget
{
@@ -64,6 +65,6 @@ class RendererObjectWidget : public QDialog, public Ui::RendererObjectWidget
private:
RenderObjectHighlighter* highlighter_;
-
+ TextBrowserWidget* textBrowser_;
};
diff --git a/widgets/rendererWidget/rendererObjectWidget.ui b/widgets/rendererWidget/rendererObjectWidget.ui
index 188c55aad807a9deb5283bec61ceecb41f19cd60..e620fbe2ab27495c37c3517b49987618581c58fb 100644
--- a/widgets/rendererWidget/rendererObjectWidget.ui
+++ b/widgets/rendererWidget/rendererObjectWidget.ui
@@ -7,7 +7,7 @@
0
0
939
- 527
+ 513
@@ -62,7 +62,7 @@
-
-
+
-