logic: extended CodeView to show locations of edges to the active Token and merge overlapping snippets
This commit is contained in:
@@ -36,10 +36,13 @@ const std::string& QtCodeFile::getFileName() const
|
||||
}
|
||||
|
||||
void QtCodeFile::addCodeSnippet(
|
||||
const std::string& str, const TokenLocationFile& locationFile, int startLineNumber, Id activeTokenId
|
||||
int startLineNumber,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile,
|
||||
const std::vector<Id>& activeTokenIds
|
||||
){
|
||||
std::shared_ptr<QtCodeSnippet> snippet(
|
||||
new QtCodeSnippet(m_parentView, str, locationFile, startLineNumber, activeTokenId, this)
|
||||
new QtCodeSnippet(m_parentView, startLineNumber, code, locationFile, activeTokenIds, this)
|
||||
);
|
||||
layout()->addWidget(snippet.get());
|
||||
m_snippets.push_back(snippet);
|
||||
|
||||
@@ -22,7 +22,10 @@ public:
|
||||
const std::string& getFileName() const;
|
||||
|
||||
void addCodeSnippet(
|
||||
const std::string& str, const TokenLocationFile& locationFile, int startLineNumber, Id activeTokenId
|
||||
int startLineNumber,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile,
|
||||
const std::vector<Id>& activeTokenIds
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
@@ -34,16 +34,16 @@ void QtCodeSnippet::LineNumberArea::paintEvent(QPaintEvent *event)
|
||||
|
||||
QtCodeSnippet::QtCodeSnippet(
|
||||
QtCodeView* parentView,
|
||||
int startLineNumber,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile,
|
||||
int startLineNumber,
|
||||
Id activeTokenId,
|
||||
const std::vector<Id>& activeTokenIds,
|
||||
QWidget *parent
|
||||
)
|
||||
: QPlainTextEdit(parent)
|
||||
, m_parentView(parentView)
|
||||
, m_startLineNumber(startLineNumber)
|
||||
, m_activeTokenId(activeTokenId)
|
||||
, m_activeTokenIds(activeTokenIds)
|
||||
, m_digits(0)
|
||||
{
|
||||
setObjectName("code_snippet");
|
||||
@@ -171,7 +171,9 @@ void QtCodeSnippet::annotateText(const TokenLocationFile& locationFile)
|
||||
m_annotations.push_back(annotation);
|
||||
|
||||
Colori color;
|
||||
if (location->getTokenId() == m_activeTokenId)
|
||||
const std::vector<Id>& ids = m_activeTokenIds;
|
||||
bool isActive = std::find(ids.begin(), ids.end(), location->getTokenId()) != ids.end();
|
||||
if (isActive)
|
||||
{
|
||||
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ public:
|
||||
|
||||
QtCodeSnippet(
|
||||
QtCodeView* parentView,
|
||||
int startLineNumber,
|
||||
const std::string& code,
|
||||
const TokenLocationFile& locationFile,
|
||||
int startLineNumber,
|
||||
Id activeTokenId,
|
||||
const std::vector<Id>& activeTokenIds,
|
||||
QWidget *parent = 0
|
||||
);
|
||||
virtual ~QtCodeSnippet();
|
||||
@@ -81,7 +81,7 @@ private:
|
||||
|
||||
QWidget *m_lineNumberArea;
|
||||
const int m_startLineNumber;
|
||||
const Id m_activeTokenId;
|
||||
const std::vector<Id> m_activeTokenIds;
|
||||
int m_digits;
|
||||
|
||||
std::vector<Annotation> m_annotations;
|
||||
|
||||
@@ -99,7 +99,7 @@ void QtCodeView::doAddCodeSnippet(const CodeSnippetParams params)
|
||||
m_frame->layout()->addWidget(file);
|
||||
}
|
||||
|
||||
file->addCodeSnippet(params.code, params.locationFile, params.startLineNumber, params.activeTokenId);
|
||||
file->addCodeSnippet(params.startLineNumber, params.code, params.locationFile, params.activeTokenIds);
|
||||
}
|
||||
|
||||
void QtCodeView::doClearCodeSnippets()
|
||||
|
||||
@@ -28,7 +28,7 @@ ComponentFactory::~ComponentFactory()
|
||||
std::shared_ptr<Component> ComponentFactory::createCodeComponent()
|
||||
{
|
||||
std::shared_ptr<CodeView> view = m_viewFactory->createCodeView(m_viewLayout);
|
||||
std::shared_ptr<CodeController> controller = std::make_shared<CodeController>(m_locationAccess);
|
||||
std::shared_ptr<CodeController> controller = std::make_shared<CodeController>(m_graphAccess, m_locationAccess);
|
||||
|
||||
std::shared_ptr<Component> component = std::make_shared<Component>(view, controller);
|
||||
return component;
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
#include "component/controller/CodeController.h"
|
||||
|
||||
#include "component/view/CodeView.h"
|
||||
#include "data/access/GraphAccess.h"
|
||||
#include "data/access/LocationAccess.h"
|
||||
#include "data/location/TokenLocation.h"
|
||||
#include "data/location/TokenLocationCollection.h"
|
||||
#include "data/location/TokenLocationFile.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
|
||||
CodeController::CodeController(LocationAccess* locationAccess)
|
||||
: m_locationAccess(locationAccess)
|
||||
CodeController::CodeController(GraphAccess* graphAccess, LocationAccess* locationAccess)
|
||||
: m_graphAccess(graphAccess)
|
||||
, m_locationAccess(locationAccess)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -19,23 +20,25 @@ CodeController::~CodeController()
|
||||
|
||||
void CodeController::setActiveTokenId(Id id)
|
||||
{
|
||||
const unsigned int lineRadius = 2;
|
||||
const uint lineRadius = 2;
|
||||
|
||||
getView()->clearCodeSnippets();
|
||||
|
||||
TokenLocationCollection collection = m_locationAccess->getTokenLocationsForTokenId(id);
|
||||
collection.forEachTokenLocation(
|
||||
[&](TokenLocation* tokenLocation) -> void
|
||||
{
|
||||
if (tokenLocation->isStartTokenLocation())
|
||||
{
|
||||
const std::string filePath = tokenLocation->getFilePath();
|
||||
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(filePath);
|
||||
std::vector<Id> activeTokenIds = m_graphAccess->getActiveTokenIdsForId(id);
|
||||
std::vector<Id> locationIds = m_graphAccess->getLocationIdsForTokenIds(activeTokenIds);
|
||||
|
||||
unsigned int firstLineNumber = std::max<int>(1, tokenLocation->getLineNumber() - lineRadius);
|
||||
unsigned int lastLineNumber = std::min<int>(
|
||||
textAccess->getLineCount(), tokenLocation->getEndTokenLocation()->getLineNumber() + lineRadius
|
||||
);
|
||||
TokenLocationCollection collection = m_locationAccess->getTokenLocationsForLocationIds(locationIds);
|
||||
collection.forEachTokenLocationFile(
|
||||
[&](TokenLocationFile* file) -> void
|
||||
{
|
||||
const std::string filePath = file->getFilePath();
|
||||
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(filePath);
|
||||
|
||||
std::vector<std::pair<uint, uint>> ranges = getSnippetRangesForFile(file, lineRadius);
|
||||
for (const std::pair<uint, uint>& range: ranges)
|
||||
{
|
||||
unsigned int firstLineNumber = std::max<int>(1, range.first - lineRadius);
|
||||
unsigned int lastLineNumber = std::min<int>(textAccess->getLineCount(), range.second + lineRadius);
|
||||
|
||||
CodeView::CodeSnippetParams params;
|
||||
for (const std::string& line: textAccess->getLines(firstLineNumber, lastLineNumber))
|
||||
@@ -46,7 +49,7 @@ void CodeController::setActiveTokenId(Id id)
|
||||
params.startLineNumber = firstLineNumber;
|
||||
params.locationFile =
|
||||
m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber);
|
||||
params.activeTokenId = id;
|
||||
params.activeTokenIds = activeTokenIds;
|
||||
|
||||
getView()->addCodeSnippet(params);
|
||||
}
|
||||
@@ -68,3 +71,40 @@ CodeView* CodeController::getView()
|
||||
{
|
||||
return Controller::getView<CodeView>();
|
||||
}
|
||||
|
||||
std::vector<std::pair<uint, uint>> CodeController::getSnippetRangesForFile(
|
||||
TokenLocationFile* file, const uint lineRadius
|
||||
) const
|
||||
{
|
||||
std::vector<std::pair<uint, uint>> ranges;
|
||||
uint start = 0;
|
||||
uint end = 0;
|
||||
|
||||
file->forEachTokenLocation(
|
||||
[&](TokenLocation* location) -> void
|
||||
{
|
||||
uint lineNumber = location->getLineNumber();
|
||||
|
||||
if (location->isStartTokenLocation())
|
||||
{
|
||||
if (!start)
|
||||
{
|
||||
start = lineNumber;
|
||||
}
|
||||
else if (end && lineNumber > end + 2 * lineRadius + 1)
|
||||
{
|
||||
ranges.push_back(std::make_pair(uint(start), uint(end)));
|
||||
start = lineNumber;
|
||||
end = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
end = lineNumber;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ranges.push_back(std::make_pair(uint(start), uint(end)));
|
||||
return ranges;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include "utility/types.h"
|
||||
|
||||
class CodeView;
|
||||
class GraphAccess;
|
||||
class LocationAccess;
|
||||
class TokenLocationFile;
|
||||
|
||||
struct AnnotatedText
|
||||
{
|
||||
@@ -24,7 +26,7 @@ class CodeController
|
||||
, public MessageListener<MessageRefresh>
|
||||
{
|
||||
public:
|
||||
CodeController(LocationAccess* locationAccess);
|
||||
CodeController(GraphAccess* graphAccess, LocationAccess* locationAccess);
|
||||
~CodeController();
|
||||
|
||||
void setActiveTokenId(Id id);
|
||||
@@ -32,8 +34,12 @@ public:
|
||||
private:
|
||||
virtual void handleMessage(MessageActivateToken* message);
|
||||
virtual void handleMessage(MessageRefresh* message);
|
||||
|
||||
CodeView* getView();
|
||||
|
||||
std::vector<std::pair<uint, uint>> getSnippetRangesForFile(TokenLocationFile* file, const uint lineRadius) const;
|
||||
|
||||
GraphAccess* m_graphAccess;
|
||||
LocationAccess* m_locationAccess;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,10 +14,10 @@ public:
|
||||
{
|
||||
CodeSnippetParams();
|
||||
|
||||
int startLineNumber;
|
||||
std::string code;
|
||||
TokenLocationFile locationFile;
|
||||
int startLineNumber;
|
||||
Id activeTokenId;
|
||||
std::vector<Id> activeTokenIds;
|
||||
};
|
||||
|
||||
CodeView(ViewLayout* viewLayout);
|
||||
|
||||
@@ -387,17 +387,62 @@ bool Storage::checkTokenIsNode(const Id id) const
|
||||
return false;
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getTokenLocationsForTokenId(Id id) const
|
||||
std::vector<Id> Storage::getActiveTokenIdsForId(Id tokenId) const
|
||||
{
|
||||
TokenLocationCollection ret;
|
||||
|
||||
Token* token = m_graph.getTokenById(id);
|
||||
std::vector<Id> ret;
|
||||
Token* token = m_graph.getTokenById(tokenId);
|
||||
if (!token)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Id> locationIds = token->getLocationIds();
|
||||
Node* node;
|
||||
if (token->isEdge())
|
||||
{
|
||||
node = dynamic_cast<Edge*>(token)->getTo();
|
||||
}
|
||||
else
|
||||
{
|
||||
node = dynamic_cast<Node*>(token);
|
||||
}
|
||||
|
||||
ret.push_back(node->getId());
|
||||
|
||||
node->forEachEdge(
|
||||
[&node, &ret](Edge* e)
|
||||
{
|
||||
if (e->getTo() == node)
|
||||
{
|
||||
ret.push_back(e->getId());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Id> Storage::getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
std::vector<Id> ret;
|
||||
|
||||
for (Id tokenId : tokenIds)
|
||||
{
|
||||
Token* token = m_graph.getTokenById(tokenId);
|
||||
if (!token)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.insert(ret.end(), token->getLocationIds().begin(), token->getLocationIds().end());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TokenLocationCollection Storage::getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const
|
||||
{
|
||||
TokenLocationCollection ret;
|
||||
|
||||
for (Id locationId: locationIds)
|
||||
{
|
||||
TokenLocation* location = m_locationCollection.findTokenLocationById(locationId);
|
||||
|
||||
@@ -81,8 +81,11 @@ public:
|
||||
|
||||
virtual bool checkTokenIsNode(const Id id) const;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId) const;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
// LocationAccess implementation
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenId(Id locationId) const;
|
||||
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
const std::string& fileName, unsigned int firstLineNumber, unsigned int lastLineNumber
|
||||
) const;
|
||||
|
||||
@@ -30,6 +30,9 @@ public:
|
||||
virtual std::pair<Id, Id> getNodesOfEdge(const Id id) const = 0;
|
||||
|
||||
virtual bool checkTokenIsNode(const Id id) const = 0;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId) const = 0;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
|
||||
};
|
||||
|
||||
#endif // GRAPH_ACCESS_H
|
||||
|
||||
@@ -166,3 +166,23 @@ bool GraphAccessProxy::checkTokenIsNode(const Id id) const
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<Id> GraphAccessProxy::getActiveTokenIdsForId(Id tokenId) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getActiveTokenIdsForId(tokenId);
|
||||
}
|
||||
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
std::vector<Id> GraphAccessProxy::getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getLocationIdsForTokenIds(tokenIds);
|
||||
}
|
||||
|
||||
return std::vector<Id>();
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ public:
|
||||
|
||||
virtual bool checkTokenIsNode(const Id id) const;
|
||||
|
||||
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId) const;
|
||||
virtual std::vector<Id> getLocationIdsForTokenIds(const std::vector<Id>& tokenIds) const;
|
||||
|
||||
private:
|
||||
GraphAccess* m_subject;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define LOCATION_ACCESS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "utility/types.h"
|
||||
|
||||
@@ -12,7 +13,7 @@ class LocationAccess
|
||||
{
|
||||
public:
|
||||
virtual ~LocationAccess();
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenId(Id id) const = 0;
|
||||
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const = 0;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
const std::string& fileName, unsigned int firstLineNumber, unsigned int lastLineNumber
|
||||
) const = 0;
|
||||
|
||||
@@ -29,11 +29,11 @@ void LocationAccessProxy::setSubject(LocationAccess* subject)
|
||||
m_subject = subject;
|
||||
}
|
||||
|
||||
TokenLocationCollection LocationAccessProxy::getTokenLocationsForTokenId(Id id) const
|
||||
TokenLocationCollection LocationAccessProxy::getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const
|
||||
{
|
||||
if (hasSubject())
|
||||
{
|
||||
return m_subject->getTokenLocationsForTokenId(id);
|
||||
return m_subject->getTokenLocationsForLocationIds(locationIds);
|
||||
}
|
||||
|
||||
return TokenLocationCollection();
|
||||
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
void setSubject(LocationAccess* subject);
|
||||
|
||||
// LocationAccess implementation
|
||||
virtual TokenLocationCollection getTokenLocationsForTokenId(Id id) const;
|
||||
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const;
|
||||
virtual TokenLocationFile getTokenLocationsForLinesInFile(
|
||||
const std::string& fileName, unsigned int firstLineNumber, unsigned int lastLineNumber
|
||||
) const;
|
||||
|
||||
@@ -3,4 +3,6 @@
|
||||
|
||||
typedef unsigned long Id;
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
#endif // TYPES_H
|
||||
|
||||
Reference in New Issue
Block a user