Files
Sourcetrail/src/lib/component/view/GraphViewStyle.cpp
T
Eberhard Graether f5f4eed509 ui: extended color scheme and added new color scheme bad_rainbow
* added color scheme template
* define fill, border, text, icon and hatching colors for each node with states normal and focus
* define colors for each edge with states normal and focus
* use default node and edge colors when no type specific ones are defined
* use normal colors for nodes and edges when no focused are defined
* allow nodes and edges to imitate look of others with "like" tag
* added style for bundle
* added style for count circle
2015-11-20 15:24:20 +01:00

575 lines
12 KiB
C++

#include "component/view/GraphViewStyle.h"
#include "utility/logging/logging.h"
#include "component/view/GraphViewStyleImpl.h"
#include "settings/ApplicationSettings.h"
#include "settings/ColorScheme.h"
int GraphViewStyle::s_gridCellSize = 5;
int GraphViewStyle::s_gridCellPadding = 10;
std::map<Node::NodeType, float> GraphViewStyle::s_charWidths;
std::map<Node::NodeType, float> GraphViewStyle::s_charHeights;
std::shared_ptr<GraphViewStyleImpl> GraphViewStyle::s_impl;
int GraphViewStyle::s_fontSize;
std::string GraphViewStyle::s_fontName;
float GraphViewStyle::s_zoomFactor;
std::map<std::string, GraphViewStyle::NodeColor> GraphViewStyle::s_nodeColors;
std::map<std::string, std::string> GraphViewStyle::s_edgeColors;
GraphViewStyle::NodeMargins::NodeMargins()
: left(0)
, right(0)
, top(0)
, bottom(0)
, spacingX(0)
, spacingY(0)
, minWidth(0)
, charWidth(0.0f)
, charHeight(0.0f)
, iconWidth(0)
{
}
GraphViewStyle::NodeStyle::NodeStyle()
: cornerRadius(0)
, borderWidth(0)
, borderDashed(false)
, fontSize(0)
, fontBold(false)
, iconSize(0)
, hasHatching(false)
{
}
GraphViewStyle::EdgeStyle::EdgeStyle()
: width(0)
, zValue(0)
, isStraight(false)
, arrowLength(0)
, arrowWidth(0)
, arrowClosed(false)
, cornerRadius(0)
, verticalOffset(0)
{
}
std::shared_ptr<GraphViewStyleImpl> GraphViewStyle::getImpl()
{
if (!s_impl)
{
LOG_ERROR("No GraphViewStyleImpl instance set.");
return nullptr;
}
return s_impl;
}
void GraphViewStyle::setImpl(std::shared_ptr<GraphViewStyleImpl> impl)
{
s_impl = impl;
}
void GraphViewStyle::loadStyleSettings()
{
s_fontSize = 14;
s_fontName = ApplicationSettings::getInstance()->getFontName();
s_zoomFactor = ApplicationSettings::getInstance()->getFontSize() / float(s_fontSize);
s_charWidths.clear();
s_charHeights.clear();
s_nodeColors.clear();
s_edgeColors.clear();
}
float GraphViewStyle::getCharWidthForNodeType(Node::NodeType type)
{
std::map<Node::NodeType, float>::const_iterator it = s_charWidths.find(type);
if (it != s_charWidths.end())
{
return it->second;
}
float charWidth = getImpl()->getCharWidthForNodeType(type);
s_charWidths.emplace(type, charWidth);
return charWidth;
}
float GraphViewStyle::getCharHeightForNodeType(Node::NodeType type)
{
std::map<Node::NodeType, float>::const_iterator it = s_charHeights.find(type);
if (it != s_charHeights.end())
{
return it->second;
}
float charHeight = getImpl()->getCharHeightForNodeType(type);
s_charHeights.emplace(type, charHeight);
return charHeight;
}
size_t GraphViewStyle::getFontSizeForNodeType(Node::NodeType type)
{
switch (type)
{
case Node::NODE_UNDEFINED:
case Node::NODE_NAMESPACE:
return s_fontSize - 2;
case Node::NODE_TYPE:
case Node::NODE_STRUCT:
case Node::NODE_CLASS:
case Node::NODE_ENUM:
case Node::NODE_TYPEDEF:
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
case Node::NODE_FILE:
case Node::NODE_MACRO:
return s_fontSize;
case Node::NODE_FUNCTION:
case Node::NODE_METHOD:
case Node::NODE_GLOBAL_VARIABLE:
case Node::NODE_FIELD:
case Node::NODE_ENUM_CONSTANT:
return s_fontSize - 3;
}
}
size_t GraphViewStyle::getFontSizeOfAccessNode()
{
return s_fontSize - 3;
}
size_t GraphViewStyle::getFontSizeOfExpandToggleNode()
{
return s_fontSize - 3;
}
size_t GraphViewStyle::getFontSizeOfCountCircle()
{
return s_fontSize - 3;
}
std::string GraphViewStyle::getFontNameForNodeType(Node::NodeType type)
{
return s_fontName;
}
std::string GraphViewStyle::getFontNameOfAccessNode()
{
return "Myriad Pro";
}
std::string GraphViewStyle::getFontNameOfExpandToggleNode()
{
return "Myriad Pro";
}
GraphViewStyle::NodeMargins GraphViewStyle::getMarginsForNodeType(Node::NodeType type, bool hasChildren)
{
NodeMargins margins;
margins.spacingX = 6;
margins.spacingY = 8;
switch (type)
{
case Node::NODE_UNDEFINED:
case Node::NODE_NAMESPACE:
margins.left = margins.right = 15;
margins.top = 10;
margins.bottom = 15;
break;
case Node::NODE_ENUM:
case Node::NODE_TYPEDEF:
case Node::NODE_FILE:
case Node::NODE_MACRO:
margins.iconWidth = s_fontSize + 11;
case Node::NODE_TYPE:
case Node::NODE_STRUCT:
case Node::NODE_CLASS:
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
if (hasChildren)
{
margins.left = margins.right = 10;
margins.top = 15;
margins.bottom = 10;
}
else
{
margins.left = margins.right = 8;
margins.top = margins.bottom = 8;
}
break;
case Node::NODE_FUNCTION:
case Node::NODE_METHOD:
case Node::NODE_GLOBAL_VARIABLE:
case Node::NODE_FIELD:
case Node::NODE_ENUM_CONSTANT:
margins.left = margins.right = 5;
margins.top = margins.bottom = 3;
break;
}
margins.charWidth = getCharWidthForNodeType(type);
margins.charHeight = getCharHeightForNodeType(type);
return margins;
}
GraphViewStyle::NodeMargins GraphViewStyle::getMarginsOfAccessNode(TokenComponentAccess::AccessType type)
{
NodeMargins margins;
margins.spacingX = margins.spacingY = 8;
margins.left = margins.right = 10;
margins.top = 40;
margins.bottom = 10;
switch (type)
{
case TokenComponentAccess::ACCESS_NONE:
margins.minWidth = 30;
break;
case TokenComponentAccess::ACCESS_PUBLIC:
margins.minWidth = 56;
break;
case TokenComponentAccess::ACCESS_PROTECTED:
margins.minWidth = 80;
break;
case TokenComponentAccess::ACCESS_PRIVATE:
margins.minWidth = 64;
break;
}
return margins;
}
GraphViewStyle::NodeMargins GraphViewStyle::getMarginsOfExpandToggleNode()
{
NodeMargins margins;
margins.left = margins.right = margins.top = margins.bottom = 6;
margins.minWidth = margins.charHeight = getFontSizeOfExpandToggleNode();
return margins;
}
GraphViewStyle::NodeMargins GraphViewStyle::getMarginsOfBundleNode()
{
return getMarginsForNodeType(Node::NODE_ENUM, false);
}
GraphViewStyle::NodeStyle GraphViewStyle::getStyleForNodeType(
Node::NodeType type, bool defined, bool isActive, bool isFocused, bool hasChildren
){
NodeStyle style;
style.color = getNodeColor(Node::getTypeString(type), isActive || isFocused);
style.fontName = getFontNameForNodeType(type);
style.fontSize = getFontSizeForNodeType(type);
switch (type)
{
case Node::NODE_UNDEFINED:
style.borderDashed = true;
case Node::NODE_NAMESPACE:
style.cornerRadius = 20;
style.textOffset.x = 15;
style.textOffset.y = 6;
break;
case Node::NODE_TYPE:
case Node::NODE_STRUCT:
case Node::NODE_CLASS:
case Node::NODE_ENUM:
case Node::NODE_TYPEDEF:
case Node::NODE_TEMPLATE_PARAMETER_TYPE:
case Node::NODE_FILE:
case Node::NODE_MACRO:
if (hasChildren)
{
style.cornerRadius = 20;
style.textOffset.x = 10;
style.textOffset.y = 8;
}
else
{
style.cornerRadius = 10;
style.textOffset.x = 8;
style.textOffset.y = 8;
}
break;
case Node::NODE_FUNCTION:
case Node::NODE_METHOD:
case Node::NODE_GLOBAL_VARIABLE:
case Node::NODE_FIELD:
case Node::NODE_ENUM_CONSTANT:
style.cornerRadius = 8;
style.textOffset.x = 5;
style.textOffset.y = 3;
break;
}
if (isActive)
{
style.borderWidth = 2;
}
else
{
style.borderWidth = 1;
}
if (isActive || isFocused)
{
style.fontBold = true;
}
style.hasHatching = !defined;
addIcon(type, hasChildren, &style);
return style;
}
GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfAccessNode()
{
NodeStyle style;
style.color = getNodeColor("access", false);
style.cornerRadius = 12;
style.fontName = getFontNameOfAccessNode();
style.fontSize = getFontSizeOfAccessNode();
style.fontBold = true;
style.textOffset.x = 10;
style.textOffset.y = 10;
return style;
}
GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfExpandToggleNode()
{
NodeStyle style;
style.color = getNodeColor("access", false);
style.cornerRadius = 100;
style.fontName = getFontNameOfExpandToggleNode();
style.fontSize = getFontSizeOfExpandToggleNode();
return style;
}
GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfCountCircle()
{
NodeStyle style;
style.color = getNodeColor("count_number", false);
style.fontName = getFontNameOfExpandToggleNode();
style.fontSize = getFontSizeOfCountCircle();
return style;
}
GraphViewStyle::NodeStyle GraphViewStyle::getStyleOfBundleNode(bool isFocused)
{
NodeStyle style = getStyleForNodeType(Node::NODE_CLASS, true, false, isFocused, false);
style.color = getNodeColor("bundle", isFocused);
addIcon(Node::NODE_ENUM, false, &style);
style.iconPath = "data/gui/graph_view/images/bundle.png";
return style;
}
GraphViewStyle::EdgeStyle GraphViewStyle::getStyleForEdgeType(Edge::EdgeType type, bool isActive, bool isFocused)
{
EdgeStyle style;
style.width = isActive ? 3 : 1;
style.zValue = isActive ? 5 : 2;
style.arrowLength = 5;
style.arrowWidth = 8;
style.cornerRadius = 10;
style.verticalOffset = 2;
style.originOffset.x = 17;
style.targetOffset.x = 17;
style.originOffset.y = -1;
style.targetOffset.y = 1;
style.color = getEdgeColor(Edge::getTypeString(type), isActive || isFocused);
switch (type)
{
case Edge::EDGE_AGGREGATION:
style.isStraight = true;
style.width = 4;
style.zValue = isActive ? -2 : -5;
break;
case Edge::EDGE_CALL:
style.originOffset.y = 1;
style.targetOffset.y = -1;
style.verticalOffset = 4;
break;
case Edge::EDGE_USAGE:
style.originOffset.y = 3;
style.targetOffset.y = -3;
style.verticalOffset = 6;
break;
case Edge::EDGE_INHERITANCE:
style.arrowLength = 20;
style.arrowWidth = 14;
style.arrowClosed = true;
style.targetOffset.x = 34;
break;
default:
break;
}
return style;
}
int GraphViewStyle::toGridOffset(int x)
{
if (x < 1)
{
return 0;
}
int r = 0;
while (r < x - 1)
{
r += s_gridCellPadding + s_gridCellSize;
}
return r;
}
int GraphViewStyle::toGridSize(int x)
{
if (x < 1)
{
return 0;
}
return s_gridCellSize + toGridOffset(x - s_gridCellSize);
}
int GraphViewStyle::toGridGap(int x)
{
if (x < 1)
{
return 0;
}
return s_gridCellPadding + toGridOffset(x - s_gridCellPadding);
}
float GraphViewStyle::getZoomFactor()
{
return s_zoomFactor;
}
const GraphViewStyle::NodeColor& GraphViewStyle::getNodeColor(const std::string& typeStr, bool focus)
{
std::string type = focus ? typeStr + "focus" : typeStr;
std::map<std::string, NodeColor>::const_iterator it = s_nodeColors.find(type);
if (it != s_nodeColors.end())
{
return it->second;
}
NodeColor color;
ColorScheme* scheme = ColorScheme::getInstance().get();
ColorScheme::ColorState state = focus ? ColorScheme::FOCUS : ColorScheme::NORMAL;
color.fill = scheme->getNodeTypeColor(typeStr, "fill", state);
color.border = scheme->getNodeTypeColor(typeStr, "border", state);
color.text = scheme->getNodeTypeColor(typeStr, "text", state);
color.icon = scheme->getNodeTypeColor(typeStr, "icon", state);
color.hatching = scheme->getNodeTypeColor(typeStr, "hatching", state);
s_nodeColors.emplace(type, color);
return s_nodeColors.find(type)->second;
}
const std::string& GraphViewStyle::getEdgeColor(const std::string& typeStr, bool focus)
{
std::string type = focus ? typeStr + "focus" : typeStr;
std::map<std::string, std::string>::const_iterator it = s_edgeColors.find(type);
if (it != s_edgeColors.end())
{
return it->second;
}
ColorScheme* scheme = ColorScheme::getInstance().get();
ColorScheme::ColorState state = focus ? ColorScheme::FOCUS : ColorScheme::NORMAL;
std::string color = scheme->getEdgeTypeColor(typeStr, state);
s_edgeColors.emplace(type, color);
return s_edgeColors.find(type)->second;
}
void GraphViewStyle::addIcon(Node::NodeType type, bool hasChildren, NodeStyle* style)
{
switch (type)
{
case Node::NODE_ENUM:
style->iconPath = "data/gui/graph_view/images/enum_1.png";
break;
case Node::NODE_TYPEDEF:
style->iconPath = "data/gui/graph_view/images/typedef_2.png";
break;
case Node::NODE_MACRO:
style->iconPath = "data/gui/graph_view/images/macro_3.png";
break;
case Node::NODE_FILE:
style->iconPath = "data/gui/graph_view/images/file.png";
break;
default:
return;
}
style->iconSize = s_fontSize + 2;
if (hasChildren)
{
style->iconOffset.x = 11;
style->textOffset.x = 6;
}
else
{
style->iconOffset.x = 9;
}
style->iconOffset.y = 9;
}