Skip to content
Snippets Groups Projects
Commit a794154d authored by Roberto Raggi's avatar Roberto Raggi
Browse files

Added indenter, code folding and automagically brace insertion to the GLSL editor.

parent 20b58e4e
No related branches found
No related tags found
No related merge requests found
......@@ -55,6 +55,9 @@ public:
bool is(int k) const { return k == kind; }
bool isNot(int k) const { return k != kind; }
int begin() const { return position; }
int end() const { return position + length; }
};
class GLSL_EXPORT Lexer
......
......@@ -5,6 +5,7 @@
<sub-class-of type="text/plain"/>
<comment>GLSL file</comment>
<glob pattern="*.glsl"/>
<glob pattern="*.shader"/>
<glob pattern="*.frag"/>
<glob pattern="*.vert"/>
<glob pattern="*.fsh"/>
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "glslautocompleter.h"
#include <Token.h>
#include <cplusplus/SimpleLexer.h>
#include <cplusplus/MatchingText.h>
#include <cplusplus/BackwardsScanner.h>
#include <QtCore/QLatin1Char>
#include <QtGui/QTextCursor>
using namespace GLSLEditor;
using namespace Internal;
using namespace CPlusPlus;
GLSLCompleter::GLSLCompleter()
{}
GLSLCompleter::~GLSLCompleter()
{}
bool GLSLCompleter::doContextAllowsAutoParentheses(const QTextCursor &cursor,
const QString &textToInsert) const
{
QChar ch;
if (! textToInsert.isEmpty())
ch = textToInsert.at(0);
if (! (MatchingText::shouldInsertMatchingText(cursor)
|| ch == QLatin1Char('\'')
|| ch == QLatin1Char('"')))
return false;
else if (isInComment(cursor))
return false;
return true;
}
bool GLSLCompleter::doContextAllowsElectricCharacters(const QTextCursor &cursor) const
{
const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(),
BackwardsScanner::previousBlockState(cursor.block()));
// XXX Duplicated from CPPEditor::isInComment to avoid tokenizing twice
if (tk.isComment()) {
const unsigned pos = cursor.selectionEnd() - cursor.block().position();
if (pos == tk.end()) {
if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
return false;
const int state = cursor.block().userState() & 0xFF;
if (state > 0)
return false;
}
if (pos < tk.end())
return false;
}
else if (tk.is(T_STRING_LITERAL) || tk.is(T_WIDE_STRING_LITERAL)
|| tk.is(T_CHAR_LITERAL) || tk.is(T_WIDE_CHAR_LITERAL)) {
const unsigned pos = cursor.selectionEnd() - cursor.block().position();
if (pos <= tk.end())
return false;
}
return true;
}
bool GLSLCompleter::doIsInComment(const QTextCursor &cursor) const
{
const Token tk = SimpleLexer::tokenAt(cursor.block().text(), cursor.positionInBlock(),
BackwardsScanner::previousBlockState(cursor.block()));
if (tk.isComment()) {
const unsigned pos = cursor.selectionEnd() - cursor.block().position();
if (pos == tk.end()) {
if (tk.is(T_CPP_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))
return true;
const int state = cursor.block().userState() & 0xFF;
if (state > 0)
return true;
}
if (pos < tk.end())
return true;
}
return false;
}
QString GLSLCompleter::doInsertMatchingBrace(const QTextCursor &cursor,
const QString &text,
QChar la,
int *skippedChars) const
{
MatchingText m;
return m.insertMatchingBrace(cursor, text, la, skippedChars);
}
QString GLSLCompleter::doInsertParagraphSeparator(const QTextCursor &cursor) const
{
MatchingText m;
return m.insertParagraphSeparator(cursor);
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef GLSLAUTOCOMPLETER_H
#define GLSLAUTOCOMPLETER_H
#include <texteditor/autocompleter.h>
namespace GLSLEditor {
namespace Internal {
class GLSLCompleter : public TextEditor::AutoCompleter
{
public:
GLSLCompleter();
virtual ~GLSLCompleter();
private:
virtual bool doContextAllowsAutoParentheses(const QTextCursor &cursor,
const QString &textToInsert = QString()) const;
virtual bool doContextAllowsElectricCharacters(const QTextCursor &cursor) const;
virtual bool doIsInComment(const QTextCursor &cursor) const;
virtual QString doInsertMatchingBrace(const QTextCursor &cursor,
const QString &text,
QChar la,
int *skippedChars) const;
virtual QString doInsertParagraphSeparator(const QTextCursor &cursor) const;
};
} // Internal
} // GLSLEditor
#endif // GLSLAUTOCOMPLETER_H
......@@ -32,6 +32,8 @@
#include "glsleditorconstants.h"
#include "glsleditorplugin.h"
#include "glslhighlighter.h"
#include "glslautocompleter.h"
#include "glslindenter.h"
#include <glsl/glsllexer.h>
#include <glsl/glslparser.h>
......@@ -85,7 +87,8 @@ GLSLTextEditor::GLSLTextEditor(QWidget *parent) :
setParenthesesMatchingEnabled(true);
setMarksVisible(true);
setCodeFoldingSupported(true);
//setIndenter(new Indenter);
setIndenter(new GLSLIndenter());
setAutoCompleter(new GLSLCompleter());
m_updateDocumentTimer = new QTimer(this);
m_updateDocumentTimer->setInterval(UPDATE_DOCUMENT_DEFAULT_INTERVAL);
......
......@@ -16,8 +16,10 @@ glsleditoreditable.h \
glsleditorfactory.h \
glsleditorplugin.h \
glslfilewizard.h \
glslhighlighter.h \
glslcodecompletion.h
glslhighlighter.h \
glslcodecompletion.h \
glslautocompleter.h \
glslindenter.h
SOURCES += \
glsleditor.cpp \
......@@ -26,8 +28,10 @@ glsleditoreditable.cpp \
glsleditorfactory.cpp \
glsleditorplugin.cpp \
glslfilewizard.cpp \
glslhighlighter.cpp \
glslcodecompletion.cpp
glslhighlighter.cpp \
glslcodecompletion.cpp \
glslautocompleter.cpp \
glslindenter.cpp
OTHER_FILES += GLSLEditor.mimetypes.xml
RESOURCES += glsleditor.qrc
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/texteditor/texteditor.pri)
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/cpptools/cpptools.pri)
include(../../libs/glsl/glsl.pri)
include(../../libs/utils/utils.pri)
include(../../libs/cplusplus/cplusplus.pri)
......@@ -29,11 +29,13 @@
#include "glslhighlighter.h"
#include <glsl/glsllexer.h>
#include <glsl/glslparser.h>
#include <texteditor/basetextdocumentlayout.h>
#include <QtCore/QDebug>
using namespace GLSLEditor;
using namespace GLSLEditor::Internal;
using namespace TextEditor;
Highlighter::Highlighter(QTextDocument *parent)
: TextEditor::SyntaxHighlighter(parent)
......@@ -52,18 +54,314 @@ void Highlighter::setFormats(const QVector<QTextCharFormat> &formats)
void Highlighter::highlightBlock(const QString &text)
{
const int previousState = previousBlockState();
int state = 0, initialBraceDepth = 0;
if (previousState != -1) {
state = previousState & 0xff;
initialBraceDepth = previousState >> 8;
}
int braceDepth = initialBraceDepth;
const QByteArray data = text.toLatin1();
GLSL::Lexer lex(/*engine=*/ 0, data.constData(), data.size());
lex.setState(state);
lex.setScanKeywords(false);
lex.setScanComments(true);
const int variant = GLSL::Lexer::Variant_GLSL_Qt | // ### FIXME: hardcoded
GLSL::Lexer::Variant_VertexShader |
GLSL::Lexer::Variant_FragmentShader;
lex.setVariant(variant);
int initialState = state;
QList<GLSL::Token> tokens;
GLSL::Token tk;
do {
lex.yylex(&tk);
tokens.append(tk);
} while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
state = lex.state(); // refresh the state
int foldingIndent = initialBraceDepth;
if (TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(currentBlock())) {
userData->setFoldingIndent(0);
userData->setFoldingStartIncluded(false);
userData->setFoldingEndIncluded(false);
}
if (tokens.isEmpty()) {
setCurrentBlockState(previousState);
BaseTextDocumentLayout::clearParentheses(currentBlock());
if (text.length()) // the empty line can still contain whitespace
setFormat(0, text.length(), m_formats[GLSLVisualWhitespace]);
BaseTextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
return;
}
const int firstNonSpace = tokens.first().begin();
Parentheses parentheses;
parentheses.reserve(20); // assume wizard level ;-)
bool highlightAsPreprocessor = false;
for (int i = 0; i < tokens.size(); ++i) {
const GLSL::Token &tk = tokens.at(i);
int previousTokenEnd = 0;
if (i != 0) {
// mark the whitespaces
previousTokenEnd = tokens.at(i - 1).begin() +
tokens.at(i - 1).length;
}
if (previousTokenEnd != tk.begin()) {
setFormat(previousTokenEnd, tk.begin() - previousTokenEnd,
m_formats[GLSLVisualWhitespace]);
}
if (tk.is(GLSL::Parser::T_LEFT_PAREN) || tk.is(GLSL::Parser::T_LEFT_BRACE) || tk.is(GLSL::Parser::T_LEFT_BRACKET)) {
const QChar c = text.at(tk.begin());
parentheses.append(Parenthesis(Parenthesis::Opened, c, tk.begin()));
if (tk.is(GLSL::Parser::T_LEFT_BRACE)) {
++braceDepth;
// if a folding block opens at the beginning of a line, treat the entire line
// as if it were inside the folding block
if (tk.begin() == firstNonSpace) {
++foldingIndent;
BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
}
}
} else if (tk.is(GLSL::Parser::T_RIGHT_PAREN) || tk.is(GLSL::Parser::T_RIGHT_BRACE) || tk.is(GLSL::Parser::T_RIGHT_BRACKET)) {
const QChar c = text.at(tk.begin());
parentheses.append(Parenthesis(Parenthesis::Closed, c, tk.begin()));
if (tk.is(GLSL::Parser::T_RIGHT_BRACE)) {
--braceDepth;
if (braceDepth < foldingIndent) {
// unless we are at the end of the block, we reduce the folding indent
if (i == tokens.size()-1 || tokens.at(i+1).is(GLSL::Parser::T_SEMICOLON))
BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
else
foldingIndent = qMin(braceDepth, foldingIndent);
}
}
}
bool highlightCurrentWordAsPreprocessor = highlightAsPreprocessor;
if (highlightAsPreprocessor)
highlightAsPreprocessor = false;
if (false /* && i == 0 && tk.is(GLSL::Parser::T_POUND)*/) {
highlightLine(text, tk.begin(), tk.length, m_formats[GLSLPreprocessorFormat]);
highlightAsPreprocessor = true;
} else if (highlightCurrentWordAsPreprocessor && isPPKeyword(text.midRef(tk.begin(), tk.length)))
setFormat(tk.begin(), tk.length, m_formats[GLSLPreprocessorFormat]);
else if (tk.is(GLSL::Parser::T_NUMBER))
setFormat(tk.begin(), tk.length, m_formats[GLSLNumberFormat]);
else if (tk.is(GLSL::Parser::T_COMMENT)) {
highlightLine(text, tk.begin(), tk.length, m_formats[GLSLCommentFormat]);
// we need to insert a close comment parenthesis, if
// - the line starts in a C Comment (initalState != 0)
// - the first token of the line is a T_COMMENT (i == 0 && tk.is(T_COMMENT))
// - is not a continuation line (tokens.size() > 1 || ! state)
if (initialState && i == 0 && (tokens.size() > 1 || ! state)) {
--braceDepth;
// unless we are at the end of the block, we reduce the folding indent
if (i == tokens.size()-1)
BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
else
foldingIndent = qMin(braceDepth, foldingIndent);
const int tokenEnd = tk.begin() + tk.length - 1;
parentheses.append(Parenthesis(Parenthesis::Closed, QLatin1Char('-'), tokenEnd));
// clear the initial state.
initialState = 0;
}
} else if (tk.is(GLSL::Parser::T_IDENTIFIER)) {
int kind = lex.findKeyword(data.constData() + tk.position, tk.length);
if (kind == GLSL::Parser::T_RESERVED)
setFormat(tk.position, tk.length, m_formats[GLSLReservedKeyword]);
else if (kind != GLSL::Parser::T_IDENTIFIER)
setFormat(tk.position, tk.length, m_formats[GLSLKeywordFormat]);
}
}
// mark the trailing white spaces
{
const GLSL::Token tk = tokens.last();
const int lastTokenEnd = tk.begin() + tk.length;
if (text.length() > lastTokenEnd)
highlightLine(text, lastTokenEnd, text.length() - lastTokenEnd, QTextCharFormat());
}
if (! initialState && state && ! tokens.isEmpty()) {
parentheses.append(Parenthesis(Parenthesis::Opened, QLatin1Char('+'),
tokens.last().begin()));
++braceDepth;
}
BaseTextDocumentLayout::setParentheses(currentBlock(), parentheses);
// if the block is ifdefed out, we only store the parentheses, but
// do not adjust the brace depth.
if (BaseTextDocumentLayout::ifdefedOut(currentBlock())) {
braceDepth = initialBraceDepth;
foldingIndent = initialBraceDepth;
}
BaseTextDocumentLayout::setFoldingIndent(currentBlock(), foldingIndent);
// optimization: if only the brace depth changes, we adjust subsequent blocks
// to have QSyntaxHighlighter stop the rehighlighting
int currentState = currentBlockState();
if (currentState != -1) {
int oldState = currentState & 0xff;
int oldBraceDepth = currentState >> 8;
if (oldState == lex.state() && oldBraceDepth != braceDepth) {
int delta = braceDepth - oldBraceDepth;
QTextBlock block = currentBlock().next();
while (block.isValid() && block.userState() != -1) {
BaseTextDocumentLayout::changeBraceDepth(block, delta);
BaseTextDocumentLayout::changeFoldingIndent(block, delta);
block = block.next();
}
}
}
setCurrentBlockState((braceDepth << 8) | lex.state());
}
void Highlighter::highlightLine(const QString &text, int position, int length,
const QTextCharFormat &format)
{
const QTextCharFormat visualSpaceFormat = m_formats[GLSLVisualWhitespace];
const int end = position + length;
int index = position;
while (index != end) {
const bool isSpace = text.at(index).isSpace();
const int start = index;
do { ++index; }
while (index != end && text.at(index).isSpace() == isSpace);
const int tokenLength = index - start;
if (isSpace)
setFormat(start, tokenLength, visualSpaceFormat);
else if (format.isValid())
setFormat(start, tokenLength, format);
}
}
bool Highlighter::isPPKeyword(const QStringRef &text) const
{
switch (text.length())
{
case 2:
if (text.at(0) == 'i' && text.at(1) == 'f')
return true;
break;
case 4:
if (text.at(0) == 'e' && text == QLatin1String("elif"))
return true;
else if (text.at(0) == 'e' && text == QLatin1String("else"))
return true;
break;
case 5:
if (text.at(0) == 'i' && text == QLatin1String("ifdef"))
return true;
else if (text.at(0) == 'u' && text == QLatin1String("undef"))
return true;
else if (text.at(0) == 'e' && text == QLatin1String("endif"))
return true;
else if (text.at(0) == 'e' && text == QLatin1String("error"))
return true;
break;
case 6:
if (text.at(0) == 'i' && text == QLatin1String("ifndef"))
return true;
if (text.at(0) == 'i' && text == QLatin1String("import"))
return true;
else if (text.at(0) == 'd' && text == QLatin1String("define"))
return true;
else if (text.at(0) == 'p' && text == QLatin1String("pragma"))
return true;
break;
case 7:
if (text.at(0) == 'i' && text == QLatin1String("include"))
return true;
else if (text.at(0) == 'w' && text == QLatin1String("warning"))
return true;
break;
case 12:
if (text.at(0) == 'i' && text == QLatin1String("include_next"))
return true;
break;
default:
break;
}
return false;
}
#if 0
void Highlighter::highlightBlock(const QString &text)
{
const int previousState = previousBlockState();
int state = 0, initialBraceDepth = 0;
if (previousState != -1) {
state = previousState & 0xff;
initialBraceDepth = previousState >> 8;
}
int braceDepth = initialBraceDepth;
Parentheses parentheses;
parentheses.reserve(20); // assume wizard level ;-)
const QByteArray data = text.toLatin1();
GLSL::Lexer lex(/*engine=*/ 0, data.constData(), data.size());
lex.setState(qMax(0, previousBlockState()));
lex.setState(qMax(0, previousState));
lex.setScanKeywords(false);
lex.setScanComments(true);
const int variant = GLSL::Lexer::Variant_GLSL_Qt | // ### FIXME: hardcoded
GLSL::Lexer::Variant_VertexShader |
GLSL::Lexer::Variant_FragmentShader;
lex.setVariant(variant);
int foldingIndent = initialBraceDepth;
if (TextBlockUserData *userData = BaseTextDocumentLayout::testUserData(currentBlock())) {
userData->setFoldingIndent(0);
userData->setFoldingStartIncluded(false);
userData->setFoldingEndIncluded(false);
}
QList<GLSL::Token> tokens;
GLSL::Token tk;
do {
lex.yylex(&tk);
tokens.append(tk);
} while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
for (int i = 0; i < tokens.size(); ++i) {
const GLSL::Token &tk = tokens.at(i);
if (tk.is(GLSL::Parser::T_NUMBER))
setFormat(tk.position, tk.length, m_formats[GLSLNumberFormat]);
......@@ -75,7 +373,35 @@ void Highlighter::highlightBlock(const QString &text)
setFormat(tk.position, tk.length, m_formats[GLSLReservedKeyword]);
else if (kind != GLSL::Parser::T_IDENTIFIER)
setFormat(tk.position, tk.length, m_formats[GLSLKeywordFormat]);
} else if (tk.is(GLSL::Parser::T_LEFT_PAREN) || tk.is(GLSL::Parser::T_LEFT_BRACE) || tk.is(GLSL::Parser::T_LEFT_BRACKET)) {
const QChar c = text.at(tk.begin());
parentheses.append(Parenthesis(Parenthesis::Opened, c, tk.begin()));
if (tk.is(GLSL::Parser::T_LEFT_BRACE)) {
++braceDepth;
// if a folding block opens at the beginning of a line, treat the entire line
// as if it were inside the folding block
// if (tk.begin() == firstNonSpace) {
// ++foldingIndent;
// BaseTextDocumentLayout::userData(currentBlock())->setFoldingStartIncluded(true);
// }
}
} else if (tk.is(GLSL::Parser::T_RIGHT_PAREN) || tk.is(GLSL::Parser::T_RIGHT_BRACE) || tk.is(GLSL::Parser::T_RIGHT_BRACKET)) {
const QChar c = text.at(tk.begin());
parentheses.append(Parenthesis(Parenthesis::Closed, c, tk.begin()));
if (tk.is(GLSL::Parser::T_RIGHT_BRACE)) {
--braceDepth;
if (braceDepth < foldingIndent) {
// unless we are at the end of the block, we reduce the folding indent
if (i == tokens.size()-1 || tokens.at(i+1).is(GLSL::Parser::T_SEMICOLON))
BaseTextDocumentLayout::userData(currentBlock())->setFoldingEndIncluded(true);
else
foldingIndent = qMin(braceDepth, foldingIndent);
}
}
}
} while (tk.isNot(GLSL::Parser::EOF_SYMBOL));
setCurrentBlockState(lex.state());
setCurrentBlockState((braceDepth << 8) | lex.state());
}
#endif
......@@ -62,6 +62,8 @@ public:
protected:
void highlightBlock(const QString &text);
void highlightLine(const QString &text, int position, int length, const QTextCharFormat &format);
bool isPPKeyword(const QStringRef &text) const;
private:
QTextCharFormat m_formats[NumGLSLFormats];
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "glslindenter.h"
#include <cpptools/cppcodeformatter.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/tabsettings.h>
#include <QtCore/QChar>
#include <QtGui/QTextDocument>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
using namespace GLSLEditor;
using namespace Internal;
GLSLIndenter::GLSLIndenter()
{}
GLSLIndenter::~GLSLIndenter()
{}
bool GLSLIndenter::doIsElectricalCharacter(const QChar &ch) const
{
if (ch == QLatin1Char('{') ||
ch == QLatin1Char('}') ||
ch == QLatin1Char(':') ||
ch == QLatin1Char('#')) {
return true;
}
return false;
}
void GLSLIndenter::doIndentBlock(QTextDocument *doc,
const QTextBlock &block,
const QChar &typedChar,
TextEditor::BaseTextEditor *editor)
{
Q_UNUSED(doc)
const TextEditor::TabSettings &ts = editor->tabSettings();
CppTools::QtStyleCodeFormatter codeFormatter(ts);
codeFormatter.updateStateUntil(block);
int indent;
int padding;
codeFormatter.indentFor(block, &indent, &padding);
// only reindent the current line when typing electric characters if the
// indent is the same it would be if the line were empty
if (isElectricCharacter(typedChar)) {
int newlineIndent;
int newlinePadding;
codeFormatter.indentForNewLineAfter(block.previous(), &newlineIndent, &newlinePadding);
if (ts.indentationColumn(block.text()) != newlineIndent + newlinePadding)
return;
}
ts.indentLine(block, indent + padding, padding);
}
void GLSLIndenter::doIndent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
TextEditor::BaseTextEditor *editor)
{
if (cursor.hasSelection()) {
QTextBlock block = doc->findBlock(cursor.selectionStart());
const QTextBlock end = doc->findBlock(cursor.selectionEnd()).next();
const TextEditor::TabSettings &ts = editor->tabSettings();
CppTools::QtStyleCodeFormatter codeFormatter(ts);
codeFormatter.updateStateUntil(block);
QTextCursor tc = editor->textCursor();
tc.beginEditBlock();
do {
int indent;
int padding;
codeFormatter.indentFor(block, &indent, &padding);
ts.indentLine(block, indent + padding, padding);
codeFormatter.updateLineStateChange(block);
block = block.next();
} while (block.isValid() && block != end);
tc.endEditBlock();
} else {
indentBlock(doc, cursor.block(), typedChar, editor);
}
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef GLSLINDENTER_H
#define GLSLINDENTER_H
#include <texteditor/indenter.h>
namespace GLSLEditor {
namespace Internal {
class GLSLIndenter : public TextEditor::Indenter
{
public:
GLSLIndenter();
virtual ~GLSLIndenter();
private:
virtual bool doIsElectricalCharacter(const QChar &ch) const;
virtual void doIndentBlock(QTextDocument *doc,
const QTextBlock &block,
const QChar &typedChar,
TextEditor::BaseTextEditor *editor);
virtual void doIndent(QTextDocument *doc,
const QTextCursor &cursor,
const QChar &typedChar,
TextEditor::BaseTextEditor *editor);
};
} // Internal
} // GLSLEditor
#endif // GLSLINDENTER_H
......@@ -50,7 +50,7 @@ contains(QT_CONFIG, declarative) {
exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativecontext_p.h) {
minQtVersion(4, 7, 1) {
SUBDIRS += plugin_qmldesigner
SUBDIRS += plugin_qmldesigner
} else {
warning()
warning("QmlDesigner plugin has been disabled.")
......@@ -201,6 +201,7 @@ plugin_glsleditor.subdir = glsleditor
plugin_glsleditor.depends = plugin_texteditor
plugin_glsleditor.depends += plugin_coreplugin
plugin_glsleditor.depends += plugin_projectexplorer
plugin_glsleditor.depends += plugin_cpptools
plugin_qmlprojectmanager.subdir = qmlprojectmanager
plugin_qmlprojectmanager.depends = plugin_texteditor
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment