Commit e0133421 authored by Waqar Ahmed's avatar Waqar Ahmed Committed by Christoph Cullmann
Browse files

LSP: implement new tooltip UI

parent 70886726
......@@ -42,6 +42,7 @@ target_sources(
lspclientservermanager.cpp
lspclientsymbolview.cpp
lspsemantichighlighting.cpp
lsptooltip.cpp
plugin.qrc
${UI_SOURCES}
)
......
......@@ -8,6 +8,7 @@
#include "lspclienthover.h"
#include "lspclientplugin.h"
#include "lsptooltip.h"
#include "lspclient_debug.h"
......@@ -26,6 +27,7 @@ class LSPClientHoverImpl : public LSPClientHover
QSharedPointer<LSPClientServerManager> m_manager;
QSharedPointer<LSPClientServer> m_server;
LspTooltip m_tooltip;
LSPClientServer::RequestHandle m_handle;
......@@ -73,15 +75,14 @@ public:
finalTooltip.append(element.value);
}
// we need to cut this a bit if too long until we have
// something more sophisticated than a tool tip for it
if (finalTooltip.size() > 512) {
finalTooltip.resize(512);
finalTooltip.append(QStringLiteral("..."));
}
// // we need to cut this a bit if too long until we have
// // something more sophisticated than a tool tip for it
// if (finalTooltip.size() > 512) {
// finalTooltip.resize(512);
// finalTooltip.append(QStringLiteral("..."));
// }
// show tool tip: think about a better way for "large" stuff
QToolTip::showText(v->mapToGlobal(v->cursorToCoordinate(position)), finalTooltip);
m_tooltip.show(finalTooltip, v->mapToGlobal(v->cursorToCoordinate(position)), v);
};
m_handle.cancel() = m_server->documentHover(view->document()->url(), position, this, h);
......
......@@ -12,6 +12,7 @@
#include "lspclientserver.h"
#include "lspclientservermanager.h"
#include <KTextEditor/MainWindow>
#include <KTextEditor/TextHintInterface>
class LSPClientHover : public QObject, public KTextEditor::TextHintProvider
......
#include "lsptooltip.h"
#include <QDebug>
#include <QEvent>
#include <QFontMetrics>
#include <QLabel>
#include <QLayout>
#include <QMouseEvent>
#include <QString>
#include <QStyle>
#include <QTextBrowser>
#include <QTimer>
#include <QWidget>
#include <KTextEditor/ConfigInterface>
#include <KTextEditor/Editor>
#include <KTextEditor/MainWindow>
#include <KTextEditor/View>
#include <KSyntaxHighlighting/AbstractHighlighter>
#include <KSyntaxHighlighting/Definition>
#include <KSyntaxHighlighting/Format>
#include <KSyntaxHighlighting/Repository>
#include <KSyntaxHighlighting/State>
using KSyntaxHighlighting::AbstractHighlighter;
using KSyntaxHighlighting::Format;
static QString toHtmlRgbaString(const QColor &color)
{
if (color.alpha() == 0xFF)
return color.name();
QString rgba = QStringLiteral("rgba(");
rgba.append(QString::number(color.red()));
rgba.append(QLatin1Char(','));
rgba.append(QString::number(color.green()));
rgba.append(QLatin1Char(','));
rgba.append(QString::number(color.blue()));
rgba.append(QLatin1Char(','));
// this must be alphaF
rgba.append(QString::number(color.alphaF()));
rgba.append(QLatin1Char(')'));
return rgba;
}
class HtmlHl : public AbstractHighlighter
{
public:
HtmlHl()
: out(&strout)
{
}
void setText(const QString &txt)
{
text = txt;
QTextStream in(&text);
KSyntaxHighlighting::State state;
out.reset();
strout.clear();
bool li = false;
while (!in.atEnd()) {
currentLine = in.readLine();
if (currentLine.isEmpty()) {
out << "<hr>";
continue;
}
if (!li && currentLine.startsWith(QLatin1String("- "))) {
currentLine.remove(0, 2);
out << "<ul><li>";
li = true;
} else if (li && currentLine.startsWith(QLatin1String("- "))) {
currentLine.remove(0, 2);
out << "<li>";
} else if (li) {
out << "</li></ul>";
li = false;
}
state = highlightLine(currentLine, state);
if (li) {
out << "</li>";
continue;
}
out << "\n<br>";
}
}
QString html()
{
// while (!out.atEnd())
// qWarning() << out.readLine();
return strout;
}
protected:
void applyFormat(int offset, int length, const Format &format) override
{
if (!length)
return;
QVarLengthArray<QString, 1> formatOutput;
if (format.hasTextColor(theme())) {
formatOutput << toHtmlRgbaString(format.textColor(theme())) << QStringLiteral(";");
}
if (!formatOutput.isEmpty()) {
out << "<span style=\"color:";
for (const auto &o : qAsConst(formatOutput)) {
out << o;
}
out << "\">";
}
out << currentLine.mid(offset, length).toHtmlEscaped();
if (!formatOutput.isEmpty()) {
out << "</span>";
}
}
private:
QString text;
QString currentLine;
QString strout;
QTextStream out;
};
class Tooltip : public QTextBrowser
{
Q_OBJECT
public:
static Tooltip *self()
{
static Tooltip instance;
return &instance;
}
void setTooltipText(const QString &text)
{
hl.setText(text);
resizeTip(text);
setHtml(hl.html());
}
void setView(KTextEditor::View *view)
{
// view changed?
// => update definition
// => update font
if (view != m_view) {
m_view = view;
hl.setDefinition(r.definitionForFileName(view->document()->url().toString()));
updateFont();
}
}
Tooltip(QWidget *parent = nullptr)
: QTextBrowser(parent)
{
setWindowFlags(Qt::FramelessWindowHint | Qt::BypassGraphicsProxyWidget | Qt::ToolTip);
document()->setDocumentMargin(2);
setFrameStyle(QFrame::Box);
connect(&m_hideTimer, &QTimer::timeout, this, &Tooltip::hideTooltip);
auto updateColors = [this](KTextEditor::Editor *e) {
auto theme = e->theme();
hl.setTheme(theme);
auto pal = palette();
pal.setColor(QPalette::Base, theme.editorColor(KSyntaxHighlighting::Theme::BackgroundColor));
setPalette(pal);
updateFont();
};
updateColors(KTextEditor::Editor::instance());
connect(KTextEditor::Editor::instance(), &KTextEditor::Editor::configChanged, this, updateColors);
}
void updateFont()
{
if (!m_view)
return;
auto ciface = qobject_cast<KTextEditor::ConfigInterface *>(m_view);
auto font = ciface->configValue(QStringLiteral("font")).value<QFont>();
setFont(font);
}
Q_SLOT void hideTooltip()
{
close();
}
void resizeTip(const QString &text)
{
QFontMetrics fm(font());
QSize size = fm.size(0, text);
size.setHeight(std::min(size.height(), m_view->window()->height() / 3));
size.setWidth(std::min(size.width(), m_view->window()->width() / 2));
resize(size);
}
protected:
void showEvent(QShowEvent *event) override
{
m_hideTimer.start(3000);
return QTextBrowser::showEvent(event);
}
void enterEvent(QEvent *event) override
{
m_hideTimer.stop();
return QTextBrowser::enterEvent(event);
}
void leaveEvent(QEvent *event) override
{
if (!m_hideTimer.isActive()) {
hideTooltip();
}
return QTextBrowser::leaveEvent(event);
}
void mouseMoveEvent(QMouseEvent *event) override
{
auto pos = event->pos();
if (rect().contains(pos)) {
return QTextBrowser::mouseMoveEvent(event);
}
hideTooltip();
}
private:
KTextEditor::View *m_view;
QTimer m_hideTimer;
HtmlHl hl;
KSyntaxHighlighting::Repository r;
};
LspTooltip::LspTooltip()
{
}
void LspTooltip::show(const QString &text, QPoint pos, KTextEditor::View *v)
{
Tooltip::self()->setView(v);
Tooltip::self()->setTooltipText(text);
Tooltip::self()->move(pos);
Tooltip::self()->show();
}
#include "lsptooltip.moc"
#ifndef LSPTOOLTIP_H
#define LSPTOOLTIP_H
#include <QPoint>
class QWidget;
class QString;
class Tooltip;
namespace KTextEditor
{
class View;
}
class LspTooltip
{
public:
LspTooltip();
void show(const QString &text, QPoint pos, KTextEditor::View *v);
private:
Tooltip *m_tooltip;
};
#endif // LSPTOOLTIP_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment