ui: focusing multiple tokens at once

This change focuses all token locations underneath the cursor at once by extending the focus handling to use vectors.
This commit is contained in:
Eberhard Graether
2015-11-12 10:14:46 +01:00
parent 28e3880e10
commit 00b74d2f30
18 changed files with 181 additions and 157 deletions
+53 -47
View File
@@ -88,7 +88,6 @@ QtCodeArea::QtCodeArea(
, m_fileWidget(file)
, m_startLineNumber(startLineNumber)
, m_locationFile(locationFile)
, m_hoveredAnnotation(nullptr)
, m_digits(0)
, m_panningValue(-1)
, m_setIDECursorPositionAction(nullptr)
@@ -324,7 +323,7 @@ void QtCodeArea::enterEvent(QEvent* event)
void QtCodeArea::leaveEvent(QEvent* event)
{
setHoveredAnnotation(nullptr);
setHoveredAnnotations(std::vector<const Annotation*>());
}
void QtCodeArea::mousePressEvent(QMouseEvent* event)
@@ -369,7 +368,7 @@ void QtCodeArea::mouseDoubleClickEvent(QMouseEvent* event)
void QtCodeArea::mouseMoveEvent(QMouseEvent* event)
{
if (m_panningValue!= -1)
if (m_panningValue != -1)
{
int panningCurrentPosition = event->pos().x();
int deltaPos = panningCurrentPosition - m_panningValue;
@@ -383,31 +382,33 @@ void QtCodeArea::mouseMoveEvent(QMouseEvent* event)
QTextCursor cursor = this->cursorForPosition(event->pos());
std::vector<const Annotation*> annotations = getAnnotationsForPosition(cursor.position());
m_hoveredLocationIds = findLocationIdsForPosition(cursor.position());
const Annotation* annotation = findAnnotationForPosition(cursor.position());
if (annotation && annotation->isScope)
bool same = annotations.size() == m_hoveredAnnotations.size();
if (same)
{
annotation = nullptr;
for (size_t i = 0; i < annotations.size(); i++)
{
if (annotations[i] != m_hoveredAnnotations[i])
{
same = false;
break;
}
}
}
QToolTip::hideText();
if (annotation != m_hoveredAnnotation)
if (!same)
{
setHoveredAnnotation(annotation);
setHoveredAnnotations(annotations);
const std::vector<std::string>& errorMessages = m_fileWidget->getErrorMessages();
if (annotation && errorMessages.size() > annotation->tokenId)
if (annotations.size() == 1 && errorMessages.size() > annotations[0]->tokenId)
{
QToolTip::showText(event->globalPos(), QString::fromStdString(errorMessages[annotation->tokenId]));
QToolTip::showText(event->globalPos(), QString::fromStdString(errorMessages[annotations[0]->tokenId]));
}
}
else if (m_hoveredLocationIds.size())
{
updateContent();
}
}
void QtCodeArea::contextMenuEvent(QContextMenuEvent* event)
@@ -458,27 +459,6 @@ void QtCodeArea::setIDECursorPosition()
MessageMoveIDECursor(m_locationFile->getFilePath().str(), lineColumn.first, lineColumn.second).dispatch();
}
const QtCodeArea::Annotation* QtCodeArea::findAnnotationForPosition(int pos) const
{
const Annotation* annotationPtr = nullptr;
int diff = endTextEditPosition() + 1;
for (const Annotation& annotation : m_annotations)
{
if (pos >= annotation.start && pos <= annotation.end)
{
int d = annotation.end - annotation.start;
if (d < diff)
{
diff = d;
annotationPtr = &annotation;
}
}
}
return annotationPtr;
}
std::vector<Id> QtCodeArea::findLocationIdsForPosition(int pos) const
{
std::vector<Id> locationIds;
@@ -494,6 +474,21 @@ std::vector<Id> QtCodeArea::findLocationIdsForPosition(int pos) const
return locationIds;
}
std::vector<const QtCodeArea::Annotation*> QtCodeArea::getAnnotationsForPosition(int pos) const
{
std::vector<const QtCodeArea::Annotation*> annotations;
for (const Annotation& annotation : m_annotations)
{
if (!annotation.isScope && pos >= annotation.start && pos <= annotation.end)
{
annotations.push_back(&annotation);
}
}
return annotations;
}
void QtCodeArea::createAnnotations(std::shared_ptr<TokenLocationFile> locationFile)
{
locationFile->forEachStartTokenLocation(
@@ -558,20 +553,19 @@ void QtCodeArea::createAnnotations(std::shared_ptr<TokenLocationFile> locationFi
void QtCodeArea::annotateText()
{
Id focusedTokenId = m_fileWidget->getFocusedTokenId();
const std::vector<Id>& activeIds = m_fileWidget->getActiveTokenIds();
const std::vector<Id>& hoverIds = m_hoveredLocationIds;
const std::vector<Id>& focusIds = m_fileWidget->getFocusedTokenIds();
bool isError = m_fileWidget->getErrorMessages().size() > 0;
bool needsUpdate = false;
for (Annotation& annotation: m_annotations)
{
bool wasActive = annotation.isActive;
bool wasFocused = annotation.isFocused;
annotation.isActive = std::find(activeIds.begin(), activeIds.end(), annotation.tokenId) != activeIds.end();
annotation.isFocused = std::find(hoverIds.begin(), hoverIds.end(), annotation.locationId) != hoverIds.end() || (annotation.tokenId == focusedTokenId);
annotation.isFocused = std::find(focusIds.begin(), focusIds.end(), annotation.tokenId) != focusIds.end();
annotation.isError = isError;
@@ -588,18 +582,30 @@ void QtCodeArea::annotateText()
}
}
void QtCodeArea::setHoveredAnnotation(const Annotation* annotation)
void QtCodeArea::setHoveredAnnotations(const std::vector<const Annotation*>& annotations)
{
if (m_hoveredAnnotation)
if (m_hoveredAnnotations.size())
{
MessageFocusOut(m_hoveredAnnotation->tokenId).dispatch();
std::vector<Id> tokenIds;
for (const Annotation* annotation : m_hoveredAnnotations)
{
tokenIds.push_back(annotation->tokenId);
}
MessageFocusOut(tokenIds).dispatch();
}
m_hoveredAnnotation = annotation;
m_hoveredAnnotations = annotations;
if (annotation)
if (annotations.size())
{
MessageFocusIn(annotation->tokenId).dispatch();
std::vector<Id> tokenIds;
for (const Annotation* annotation : annotations)
{
tokenIds.push_back(annotation->tokenId);
}
MessageFocusIn(tokenIds).dispatch();
}
}
+4 -6
View File
@@ -130,13 +130,13 @@ private:
std::string fill;
};
const Annotation* findAnnotationForPosition(int pos) const;
std::vector<Id> findLocationIdsForPosition(int pos) const;
std::vector<const Annotation*> getAnnotationsForPosition(int pos) const;
void createAnnotations(std::shared_ptr<TokenLocationFile> locationFile);
void annotateText();
void setHoveredAnnotation(const Annotation* annotation);
void setHoveredAnnotations(const std::vector<const Annotation*>& annotations);
int toTextEditPosition(int lineNumber, int columnNumber) const;
std::pair<int, int> toLineColumn(int textEditPosition) const;
@@ -144,8 +144,8 @@ private:
int endTextEditPosition() const;
std::set<int> getActiveLineNumbers() const;
std::vector<QRect> getCursorRectsForAnnotation(const Annotation& annotation) const;
std::vector<QRect> getCursorRectsForAnnotation(const Annotation& annotation) const;
const AnnotationColor& getAnnotationColorForAnnotation(const Annotation& annotation);
void createActions();
@@ -162,9 +162,7 @@ private:
std::shared_ptr<TokenLocationFile> m_locationFile;
std::vector<Annotation> m_annotations;
const Annotation* m_hoveredAnnotation;
std::vector<Id> m_hoveredLocationIds;
std::vector<const Annotation*> m_hoveredAnnotations;
int m_digits;
int m_panningValue; // just for horizontal panning
+5 -5
View File
@@ -124,16 +124,16 @@ std::string QtCodeFile::getFileName() const
return m_filePath.fileName();
}
Id QtCodeFile::getFocusedTokenId() const
{
return m_parent->getFocusedTokenId();
}
const std::vector<Id>& QtCodeFile::getActiveTokenIds() const
{
return m_parent->getActiveTokenIds();
}
const std::vector<Id>& QtCodeFile::getFocusedTokenIds() const
{
return m_parent->getFocusedTokenIds();
}
const std::vector<std::string>& QtCodeFile::getErrorMessages() const
{
return m_parent->getErrorMessages();
+2 -1
View File
@@ -35,8 +35,9 @@ public:
const FilePath& getFilePath() const;
std::string getFileName() const;
Id getFocusedTokenId() const;
const std::vector<Id>& getActiveTokenIds() const;
const std::vector<Id>& getFocusedTokenIds() const;
const std::vector<std::string>& getErrorMessages() const;
void addCodeSnippet(
+14 -10
View File
@@ -12,7 +12,6 @@
QtCodeFileList::QtCodeFileList(QWidget* parent)
: QScrollArea(parent)
, m_focusedTokenId(0)
{
setObjectName("code_file_list_base");
@@ -77,11 +76,6 @@ void QtCodeFileList::clearCodeSnippets()
this->verticalScrollBar()->setValue(0);
}
Id QtCodeFileList::getFocusedTokenId() const
{
return m_focusedTokenId;
}
const std::vector<Id>& QtCodeFileList::getActiveTokenIds() const
{
return m_activeTokenIds;
@@ -92,6 +86,16 @@ void QtCodeFileList::setActiveTokenIds(const std::vector<Id>& activeTokenIds)
m_activeTokenIds = activeTokenIds;
}
const std::vector<Id>& QtCodeFileList::getFocusedTokenIds() const
{
return m_focusedTokenIds;
}
void QtCodeFileList::setFocusedTokenIds(const std::vector<Id>& focusedTokenIds)
{
m_focusedTokenIds = focusedTokenIds;
}
const std::vector<std::string>& QtCodeFileList::getErrorMessages() const
{
return m_errorMessages;
@@ -136,15 +140,15 @@ void QtCodeFileList::expandActiveSnippetFile()
}
}
void QtCodeFileList::focusToken(Id tokenId)
void QtCodeFileList::focusTokenIds(const std::vector<Id>& focusedTokenIds)
{
m_focusedTokenId = tokenId;
setFocusedTokenIds(focusedTokenIds);
updateFiles();
}
void QtCodeFileList::defocusToken()
void QtCodeFileList::defocusTokenIds()
{
m_focusedTokenId = 0;
setFocusedTokenIds(std::vector<Id>());
updateFiles();
}
+6 -5
View File
@@ -42,19 +42,20 @@ public:
void clearCodeSnippets();
Id getFocusedTokenId() const;
const std::vector<Id>& getActiveTokenIds() const;
void setActiveTokenIds(const std::vector<Id>& activeTokenIds);
const std::vector<Id>& getFocusedTokenIds() const;
void setFocusedTokenIds(const std::vector<Id>& focusedTokenIds);
const std::vector<std::string>& getErrorMessages() const;
void setErrorMessages(const std::vector<std::string>& errorMessages);
bool scrollToFirstActiveSnippet();
void expandActiveSnippetFile();
void focusToken(Id tokenId);
void defocusToken();
void focusTokenIds(const std::vector<Id>& focusedTokenIds);
void defocusTokenIds();
private slots:
void scrollToSnippet(QWidget* widget);
@@ -69,8 +70,8 @@ private:
std::shared_ptr<QFrame> m_frame;
std::vector<std::shared_ptr<QtCodeFile>> m_files;
Id m_focusedTokenId;
std::vector<Id> m_activeTokenIds;
std::vector<Id> m_focusedTokenIds;
std::vector<std::string> m_errorMessages;
};
+10 -10
View File
@@ -15,8 +15,8 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout)
, m_addCodeSnippetsFunctor(std::bind(&QtCodeView::doAddCodeSnippets, this, std::placeholders::_1))
, m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1))
, m_doShowFirstActiveSnippetFunctor(std::bind(&QtCodeView::doShowFirstActiveSnippet, this))
, m_focusTokenFunctor(std::bind(&QtCodeView::doFocusToken, this, std::placeholders::_1))
, m_defocusTokenFunctor(std::bind(&QtCodeView::doDefocusToken, this))
, m_focusTokenIdsFunctor(std::bind(&QtCodeView::doFocusTokenIds, this, std::placeholders::_1))
, m_defocusTokenIdsFunctor(std::bind(&QtCodeView::doDefocusTokenIds, this))
{
m_widget = new QtCodeFileList();
setStyleSheet();
@@ -70,14 +70,14 @@ void QtCodeView::showFirstActiveSnippet()
m_doShowFirstActiveSnippetFunctor();
}
void QtCodeView::focusToken(const Id tokenId)
void QtCodeView::focusTokenIds(const std::vector<Id>& focusedTokenIds)
{
m_focusTokenFunctor(tokenId);
m_focusTokenIdsFunctor(focusedTokenIds);
}
void QtCodeView::defocusToken()
void QtCodeView::defocusTokenIds()
{
m_defocusTokenFunctor();
m_defocusTokenIdsFunctor();
}
void QtCodeView::doRefreshView()
@@ -151,14 +151,14 @@ void QtCodeView::doShowFirstActiveSnippet()
}
}
void QtCodeView::doFocusToken(const Id tokenId)
void QtCodeView::doFocusTokenIds(const std::vector<Id>& focusedTokenIds)
{
m_widget->focusToken(tokenId);
m_widget->focusTokenIds(focusedTokenIds);
}
void QtCodeView::doDefocusToken()
void QtCodeView::doDefocusTokenIds()
{
m_widget->defocusToken();
m_widget->defocusTokenIds();
}
void QtCodeView::setStyleSheet() const
+6 -6
View File
@@ -35,8 +35,8 @@ public:
virtual void showFirstActiveSnippet();
virtual void focusToken(const Id tokenId);
virtual void defocusToken();
virtual void focusTokenIds(const std::vector<Id>& focusedTokenIds);
virtual void defocusTokenIds();
private:
void doRefreshView();
@@ -47,8 +47,8 @@ private:
void doShowFirstActiveSnippet();
void doFocusToken(const Id tokenId);
void doDefocusToken();
void doFocusTokenIds(const std::vector<Id>& focusedTokenIds);
void doDefocusTokenIds();
void setStyleSheet() const;
@@ -57,8 +57,8 @@ private:
QtThreadedFunctor<const std::vector<CodeSnippetParams>&> m_addCodeSnippetsFunctor;
QtThreadedFunctor<const CodeSnippetParams&> m_showCodeFileFunctor;
QtThreadedFunctor<> m_doShowFirstActiveSnippetFunctor;
QtThreadedFunctor<const Id&> m_focusTokenFunctor;
QtThreadedFunctor<> m_defocusTokenFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_focusTokenIdsFunctor;
QtThreadedFunctor<> m_defocusTokenIdsFunctor;
QtCodeFileList* m_widget;
+34 -28
View File
@@ -601,50 +601,56 @@ void QtGraphView::createTransition()
m_transition->start();
}
void QtGraphView::focusToken(Id tokenId)
void QtGraphView::focusTokenIds(const std::vector<Id>& focusedTokenIds)
{
m_focusInFunctor(tokenId);
m_focusInFunctor(focusedTokenIds);
}
void QtGraphView::doFocusIn(Id tokenId)
void QtGraphView::doFocusIn(const std::vector<Id>& tokenIds)
{
std::shared_ptr<QtGraphNode> node = findNodeRecursive(m_oldNodes, tokenId);
if (node && node->isDataNode())
for (const Id& tokenId : tokenIds)
{
node->focusIn();
return;
}
for (std::shared_ptr<QtGraphEdge> edge : m_oldEdges)
{
if (edge->getData() && edge->getData()->getId() == tokenId)
std::shared_ptr<QtGraphNode> node = findNodeRecursive(m_oldNodes, tokenId);
if (node && node->isDataNode())
{
edge->focusIn();
return;
node->focusIn();
continue;
}
for (std::shared_ptr<QtGraphEdge> edge : m_oldEdges)
{
if (edge->getData() && edge->getData()->getId() == tokenId)
{
edge->focusIn();
break;
}
}
}
}
void QtGraphView::defocusToken(Id tokenId)
void QtGraphView::defocusTokenIds(const std::vector<Id>& defocusedTokenIds)
{
m_focusOutFunctor(tokenId);
m_focusOutFunctor(defocusedTokenIds);
}
void QtGraphView::doFocusOut(Id tokenId)
void QtGraphView::doFocusOut(const std::vector<Id>& tokenIds)
{
std::shared_ptr<QtGraphNode> node = findNodeRecursive(m_oldNodes, tokenId);
if (node && node->isDataNode())
for (const Id& tokenId : tokenIds)
{
node->focusOut();
return;
}
for (std::shared_ptr<QtGraphEdge> edge : m_oldEdges)
{
if (edge->getData() && edge->getData()->getId() == tokenId)
std::shared_ptr<QtGraphNode> node = findNodeRecursive(m_oldNodes, tokenId);
if (node && node->isDataNode())
{
edge->focusOut();
return;
node->focusOut();
continue;
}
for (std::shared_ptr<QtGraphEdge> edge : m_oldEdges)
{
if (edge->getData() && edge->getData()->getId() == tokenId)
{
edge->focusOut();
break;
}
}
}
}
+7 -6
View File
@@ -51,8 +51,8 @@ public:
virtual void rebuildGraph(std::shared_ptr<Graph> graph, const std::vector<DummyNode>& nodes, const std::vector<DummyEdge>& edges);
virtual void clear();
virtual void focusToken(Id tokenId);
virtual void defocusToken(Id tokenId);
virtual void focusTokenIds(const std::vector<Id>& focusedTokenIds);
virtual void defocusTokenIds(const std::vector<Id>& defocusedTokenIds);
virtual void resizeView();
@@ -72,8 +72,9 @@ private:
void doClear();
void doResize();
void doRefreshView();
void doFocusIn(Id tokenId);
void doFocusOut(Id tokeId);
void doFocusIn(const std::vector<Id>& tokenIds);
void doFocusOut(const std::vector<Id>& tokenIds);
std::shared_ptr<QtGraphNode> findNodeRecursive(const std::list<std::shared_ptr<QtGraphNode>>& nodes, Id tokenId);
@@ -97,8 +98,8 @@ private:
QtThreadedFunctor<void> m_clearFunctor;
QtThreadedFunctor<void> m_resizeFunctor;
QtThreadedFunctor<void> m_refreshFunctor;
QtThreadedFunctor<Id> m_focusInFunctor;
QtThreadedFunctor<Id> m_focusOutFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_focusInFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_focusOutFunctor;
std::shared_ptr<Graph> m_graph;
std::shared_ptr<Graph> m_oldGraph;
@@ -204,7 +204,7 @@ void QtGraphEdge::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
return;
}
MessageFocusIn(getData()->getId()).dispatch();
MessageFocusIn(std::vector<Id>(1, getData()->getId())).dispatch();
}
void QtGraphEdge::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
@@ -215,7 +215,7 @@ void QtGraphEdge::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
return;
}
MessageFocusOut(getData()->getId()).dispatch();
MessageFocusOut(std::vector<Id>(1, getData()->getId())).dispatch();
}
void QtGraphEdge::setDirection(TokenComponentAggregation::Direction direction)
@@ -71,10 +71,10 @@ void QtGraphNodeData::updateStyle()
void QtGraphNodeData::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
MessageFocusIn(m_data->getId()).dispatch();
MessageFocusIn(std::vector<Id>(1, m_data->getId())).dispatch();
}
void QtGraphNodeData::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
MessageFocusOut(m_data->getId()).dispatch();
MessageFocusOut(std::vector<Id>(1, m_data->getId())).dispatch();
}
@@ -80,12 +80,12 @@ void CodeController::handleMessage(MessageActivateTokens* message)
void CodeController::handleMessage(MessageFocusIn* message)
{
getView()->focusToken(message->tokenId);
getView()->focusTokenIds(message->tokenIds);
}
void CodeController::handleMessage(MessageFocusOut* message)
{
getView()->defocusToken();
getView()->defocusTokenIds();
}
void CodeController::handleMessage(MessageShowErrors* message)
@@ -268,7 +268,7 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForFile(std:
}
);
atomicRanges = SnippetMerger::Range::mergeAdjacent(atomicRanges);
ranges = fileScopedMerger.merge(atomicRanges);
}
@@ -61,12 +61,12 @@ void GraphController::handleMessage(MessageFlushUpdates* message)
void GraphController::handleMessage(MessageFocusIn* message)
{
getView()->focusToken(message->tokenId);
getView()->focusTokenIds(message->tokenIds);
}
void GraphController::handleMessage(MessageFocusOut *message)
{
getView()->defocusToken(message->tokenId);
getView()->defocusTokenIds(message->tokenIds);
}
void GraphController::handleMessage(MessageGraphNodeBundleSplit* message)
+2 -2
View File
@@ -52,8 +52,8 @@ public:
virtual void showFirstActiveSnippet() = 0;
virtual void focusToken(const Id tokenId) = 0;
virtual void defocusToken() = 0;
virtual void focusTokenIds(const std::vector<Id>& focusedTokenIds) = 0;
virtual void defocusTokenIds() = 0;
private:
CodeController* getController();
+3 -2
View File
@@ -20,8 +20,9 @@ public:
virtual void rebuildGraph(
std::shared_ptr<Graph> graph, const std::vector<DummyNode>& nodes, const std::vector<DummyEdge>& edges) = 0;
virtual void clear() = 0;
virtual void focusToken(Id tokenId) = 0;
virtual void defocusToken(Id tokenId) = 0;
virtual void focusTokenIds(const std::vector<Id>& focusedTokenIds) = 0;
virtual void defocusTokenIds(const std::vector<Id>& defocusedTokenIds) = 0;
virtual void resizeView() = 0;
+13 -10
View File
@@ -1,23 +1,26 @@
#ifndef MESSAGE_FOCUS_IN_H
#define MESSAGE_FOCUS_IN_H
#include <vector>
#include "utility/messaging/Message.h"
#include "utility/types.h"
class MessageFocusIn : public Message<MessageFocusIn>
class MessageFocusIn
: public Message<MessageFocusIn>
{
public:
MessageFocusIn(Id tokenId)
: tokenId(tokenId)
{
}
MessageFocusIn(const std::vector<Id>& tokenIds)
: tokenIds(tokenIds)
{
}
static const std::string getStaticType()
{
return "MessageFocusIn";
}
static const std::string getStaticType()
{
return "MessageFocusIn";
}
const Id tokenId;
const std::vector<Id> tokenIds;
};
#endif //MESSAGE_FOCUS_IN_H
@@ -1,23 +1,26 @@
#ifndef MESSAGE_FOCUS_OUT_H
#define MESSAGE_FOCUS_OUT_H
#include <vector>
#include "utility/messaging/Message.h"
#include "utility/types.h"
class MessageFocusOut : public Message<MessageFocusOut>
class MessageFocusOut
: public Message<MessageFocusOut>
{
public:
MessageFocusOut(Id tokenId)
: tokenId(tokenId)
{
}
MessageFocusOut(const std::vector<Id>& tokenIds)
: tokenIds(tokenIds)
{
}
static const std::string getStaticType()
{
return "MessageHoverLeave";
}
static const std::string getStaticType()
{
return "MessageHoverLeave";
}
const Id tokenId;
const std::vector<Id> tokenIds;
};
#endif //MESSAGE_FOCUS_OUT_H