]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt/GuiDelimiter.cpp
Fix up 'Reduce metrics updates from 4 to 1 when loading file'
[lyx.git] / src / frontends / qt / GuiDelimiter.cpp
index 8dc97ffe17bdf186d1aeb3214a8b975032546fdf..479db8703395a858791a6a49acff07411e0fcf57 100644 (file)
@@ -26,6 +26,8 @@
 #include "support/gettext.h"
 #include "support/lstrings.h"
 
+#include <QBitmap>
+#include <QPainter>
 #include <QPixmap>
 #include <QCheckBox>
 #include <QListWidgetItem>
@@ -80,15 +82,40 @@ static docstring fix_name(string const & str, bool big)
 }
 
 struct MathSymbol {
-       MathSymbol(char_type uc = '?', unsigned char fc = 0,
-               FontFamily ff = SYMBOL_FAMILY)
-               : unicode(uc), fontcode(fc), fontfamily(ff)
+       MathSymbol(char_type uc = '?', string icon = string())
+               : unicode(uc), icon(icon)
        {}
        char_type unicode;
-       unsigned char fontcode;
-       FontFamily fontfamily;
+       string icon;
 };
 
+
+QPixmap getSelectedPixmap(QPixmap pixmap, QSize const icon_size)
+{
+       QPalette palette = QPalette();
+       QColor text_color = (guiApp->isInDarkMode())
+                       ? palette.color(QPalette::Active, QPalette::WindowText)
+                       : Qt::black;
+       QColor highlight_color = palette.color(QPalette::Active, QPalette::HighlightedText);
+       QColor highlight_bg = palette.color(QPalette::Active, QPalette::Highlight);
+
+       // create a layer with black text turned to QPalette::HighlightedText
+       QPixmap hl_overlay(pixmap.size());
+       hl_overlay.fill(highlight_color);
+       hl_overlay.setMask(pixmap.createMaskFromColor(text_color, Qt::MaskOutColor));
+
+       // Create highlighted background
+       QPixmap hl_background(icon_size);
+       hl_background.fill(highlight_bg);
+
+       // put layers on top of existing pixmap
+       QPainter painter(&pixmap);
+       painter.drawPixmap(pixmap.rect(), hl_background);
+       painter.drawPixmap(pixmap.rect(), hl_overlay);
+
+       return pixmap;
+}
+
 /// TeX-name / Math-symbol map.
 static map<std::string, MathSymbol> math_symbols_;
 /// Math-symbol / TeX-name map.
@@ -96,6 +123,10 @@ static map<std::string, MathSymbol> math_symbols_;
 /// \c math_symbols_.
 static map<char_type, string> tex_names_;
 
+typedef map<char_type, QListWidgetItem *> ListItems;
+ListItems left_list_items_;
+ListItems right_list_items_;
+
 void initMathSymbols()
 {
        // FIXME: Ideally, those unicode codepoints would be defined
@@ -103,34 +134,34 @@ void initMathSymbols()
        // defined with non-unicode ids for use within mathed.
        // FIXME 2: We should fill-in this map with the parsed "symbols"
        // file done in MathFactory.cpp.
-       math_symbols_["("] = MathSymbol('(', 40, CMR_FAMILY);
-       math_symbols_[")"] = MathSymbol(')', 41, CMR_FAMILY);
-       math_symbols_["{"] = MathSymbol('{', 102, CMSY_FAMILY);
-       math_symbols_["}"] = MathSymbol('}', 103, CMSY_FAMILY);
-       math_symbols_["["] = MathSymbol('[', 91, CMR_FAMILY);
-       math_symbols_["]"] = MathSymbol(']', 93, CMR_FAMILY);
-       math_symbols_["|"] = MathSymbol('|', 106, CMSY_FAMILY);
-       math_symbols_["/"] = MathSymbol('/', 47, CMR_FAMILY);
-       math_symbols_["backslash"] = MathSymbol('\\', 110, CMSY_FAMILY);
-       math_symbols_["lceil"] = MathSymbol(0x2308, 100, CMSY_FAMILY);
-       math_symbols_["rceil"] = MathSymbol(0x2309, 101, CMSY_FAMILY);
-       math_symbols_["lfloor"] = MathSymbol(0x230A, 98, CMSY_FAMILY);
-       math_symbols_["rfloor"] = MathSymbol(0x230B, 99, CMSY_FAMILY);
-       math_symbols_["langle"] = MathSymbol(0x2329, 104, CMSY_FAMILY);
-       math_symbols_["rangle"] = MathSymbol(0x232A, 105, CMSY_FAMILY);
-       math_symbols_["llbracket"] = MathSymbol(0x27e6, 74, STMARY_FAMILY);
-       math_symbols_["rrbracket"] = MathSymbol(0x27e7, 75, STMARY_FAMILY);
-       math_symbols_["uparrow"] = MathSymbol(0x2191, 34, CMSY_FAMILY);
-       math_symbols_["Uparrow"] = MathSymbol(0x21D1, 42, CMSY_FAMILY);
-       math_symbols_["updownarrow"] = MathSymbol(0x2195, 108, CMSY_FAMILY);
-       math_symbols_["Updownarrow"] = MathSymbol(0x21D5, 109, CMSY_FAMILY);
-       math_symbols_["downarrow"] = MathSymbol(0x2193, 35, CMSY_FAMILY);
-       math_symbols_["Downarrow"] = MathSymbol(0x21D3, 43, CMSY_FAMILY);
-       math_symbols_["downdownarrows"] = MathSymbol(0x21CA, 184, MSA_FAMILY);
-       math_symbols_["downharpoonleft"] = MathSymbol(0x21C3, 188, MSA_FAMILY);
-       math_symbols_["downharpoonright"] = MathSymbol(0x21C2, 186, MSA_FAMILY);
-       math_symbols_["vert"] = MathSymbol(0x007C, 106, CMSY_FAMILY);
-       math_symbols_["Vert"] = MathSymbol(0x2016, 107, CMSY_FAMILY);
+       math_symbols_["("] = MathSymbol('(', "lparen");
+       math_symbols_[")"] = MathSymbol(')', "rparen");
+       math_symbols_["{"] = MathSymbol('{', "lbrace");
+       math_symbols_["}"] = MathSymbol('}', "rbrace");
+       math_symbols_["["] = MathSymbol('[', "lbracket");
+       math_symbols_["]"] = MathSymbol(']', "rbracket");
+       math_symbols_["|"] = MathSymbol('|', "mid");
+       math_symbols_["/"] = MathSymbol('/', "slash");
+       math_symbols_["backslash"] = MathSymbol('\\', "backslash");
+       math_symbols_["lceil"] = MathSymbol(0x2308, "lceil");
+       math_symbols_["rceil"] = MathSymbol(0x2309, "rceil");
+       math_symbols_["lfloor"] = MathSymbol(0x230A, "lfloor");
+       math_symbols_["rfloor"] = MathSymbol(0x230B, "rfloor");
+       math_symbols_["langle"] = MathSymbol(0x2329, "langle");
+       math_symbols_["rangle"] = MathSymbol(0x232A, "rangle");
+       math_symbols_["llbracket"] = MathSymbol(0x27e6, "llbracket");
+       math_symbols_["rrbracket"] = MathSymbol(0x27e7, "rrbracket");
+       math_symbols_["uparrow"] = MathSymbol(0x2191, "uparrow");
+       math_symbols_["Uparrow"] = MathSymbol(0x21D1, "uparrow2");
+       math_symbols_["updownarrow"] = MathSymbol(0x2195, "updownarrow");
+       math_symbols_["Updownarrow"] = MathSymbol(0x21D5, "updownarrow2");
+       math_symbols_["downarrow"] = MathSymbol(0x2193, "downarrow");
+       math_symbols_["Downarrow"] = MathSymbol(0x21D3, "downarrow2");
+       math_symbols_["downdownarrows"] = MathSymbol(0x21CA, "downdownarrows");
+       math_symbols_["downharpoonleft"] = MathSymbol(0x21C3, "downharpoonleft");
+       math_symbols_["downharpoonright"] = MathSymbol(0x21C2, "downharpoonright");
+       math_symbols_["vert"] = MathSymbol(0x007C, "vert");
+       math_symbols_["Vert"] = MathSymbol(0x2016, "vert2");
 
        map<string, MathSymbol>::const_iterator it = math_symbols_.begin();
        map<string, MathSymbol>::const_iterator end = math_symbols_.end();
@@ -139,7 +170,7 @@ void initMathSymbols()
 }
 
 /// \return the math unicode symbol associated to a TeX name.
-MathSymbol const & mathSymbol(string tex_name)
+MathSymbol const & mathSymbol(string const & tex_name)
 {
        map<string, MathSymbol>::const_iterator it =
                math_symbols_.find(tex_name);
@@ -195,54 +226,55 @@ GuiDelimiter::GuiDelimiter(GuiView & lv)
        leftLW->setDragDropMode(QAbstractItemView::NoDragDrop);
        rightLW->setDragDropMode(QAbstractItemView::NoDragDrop);
 
+       left_list_items_.clear();
+       right_list_items_.clear();
+
        initMathSymbols();
 
-       FontInfo lyxfont;
-       lyxfont.setFamily(CMR_FAMILY);
-       QFontMetrics fm(frontend::getFont(lyxfont));
-       QSize item_size(fm.maxWidth(), fm.height() + 8);
+       QSize icon_size(26, 26);
 
-       leftLW->setMinimumWidth(5 * item_size.width());
-       rightLW->setMinimumWidth(5 * item_size.width());
+       // we calculate the appropriate width to fit 4 icons in a row
+       leftLW->setMinimumWidth((4 * (icon_size.width() + (2 * leftLW->spacing())))
+                               + (leftLW->frameWidth() * 2)
+                               + leftLW->verticalScrollBar()->height());
+       rightLW->setMinimumWidth((4 * (icon_size.width() + (2 * rightLW->spacing())))
+                                + (rightLW->frameWidth() * 2)
+                                + rightLW->verticalScrollBar()->height());
+       leftLW->setIconSize(icon_size);
+       rightLW->setIconSize(icon_size);
 
-       typedef map<char_type, QListWidgetItem *> ListItems;
-       ListItems list_items;
        // The last element is the empty one.
        int const end = nr_latex_delimiters - 1;
        for (int i = 0; i < end; ++i) {
                string const delim = latex_delimiters[i];
                MathSymbol const & ms = mathSymbol(delim);
-               QString symbol(ms.fontcode?
-                       QChar(ms.fontcode) : toqstr(docstring(1, ms.unicode)));
-               QListWidgetItem * lwi = new QListWidgetItem(symbol);
-               lyxfont.setFamily(ms.fontfamily);
-               QFont font = frontend::getFont(lyxfont);
-               lwi->setFont(font);
+               // get pixmap with bullets
+               QPixmap pixmap = getPixmap("images/math/", toqstr(ms.icon), "svgz,png");
+               QIcon icon(pixmap);
+               icon.addPixmap(getSelectedPixmap(pixmap, icon_size), QIcon::Selected);
+               QListWidgetItem * lwi = new QListWidgetItem(icon, QString());
                setDelimiterName(lwi, delim);
+               left_list_items_[ms.unicode] = lwi;
                lwi->setToolTip(toqstr(delim));
-               lwi->setSizeHint(item_size);
-               switch (ms.fontfamily) {
-               case CMSY_FAMILY:
-               case STMARY_FAMILY:
-                       // Hack to work around the broken metrics of these fonts
-                       // FIXME: Better fix the fonts or use fonts that are not broken
-                       lwi->setTextAlignment(Qt::AlignTop | Qt::AlignHCenter);
-                       break;
-               default:
-                       lwi->setTextAlignment(Qt::AlignCenter);
-               }
-               list_items[ms.unicode] = lwi;
+               lwi->setSizeHint(icon_size);
                leftLW->addItem(lwi);
        }
 
        for (int i = 0; i != leftLW->count(); ++i) {
                MathSymbol const & ms = mathSymbol(getDelimiterName(leftLW->item(i)));
-               rightLW->addItem(list_items[doMatch(ms.unicode)]->clone());
+               char_type const rdelim = doMatch(ms.unicode);
+               QListWidgetItem * rwi = left_list_items_[rdelim]->clone();
+               right_list_items_[mathSymbol(texName(rdelim)).unicode] = rwi;
+               rightLW->addItem(rwi);
        }
 
        // The last element is the empty one.
        QListWidgetItem * lwi = new QListWidgetItem(qt_("(None)"));
+       lwi->setToolTip(qt_("No Delimiter"));
+       left_list_items_['?'] = lwi;
        QListWidgetItem * rwi = new QListWidgetItem(qt_("(None)"));
+       rwi->setToolTip(qt_("No Delimiter"));
+       right_list_items_['?'] = rwi;
        leftLW->addItem(lwi);
        rightLW->addItem(rwi);
 
@@ -262,24 +294,42 @@ char_type GuiDelimiter::doMatch(char_type const symbol)
 {
        string const & str = texName(symbol);
        string match;
-       if (str == "(") match = ")";
-       else if (str == ")") match = "(";
-       else if (str == "[") match = "]";
-       else if (str == "]") match = "[";
-       else if (str == "{") match = "}";
-       else if (str == "}") match = "{";
-       else if (str == "l") match = "r";
-       else if (str == "rceil") match = "lceil";
-       else if (str == "lceil") match = "rceil";
-       else if (str == "rfloor") match = "lfloor";
-       else if (str == "lfloor") match = "rfloor";
-       else if (str == "rangle") match = "langle";
-       else if (str == "langle") match = "rangle";
-       else if (str == "llbracket") match = "rrbracket";
-       else if (str == "rrbracket") match = "llbracket";
-       else if (str == "backslash") match = "/";
-       else if (str == "/") match = "backslash";
-       else return symbol;
+       if (str == "(")
+               match = ")";
+       else if (str == ")")
+               match = "(";
+       else if (str == "[")
+               match = "]";
+       else if (str == "]")
+               match = "[";
+       else if (str == "{")
+               match = "}";
+       else if (str == "}")
+               match = "{";
+       else if (str == "l")
+               match = "r";
+       else if (str == "rceil")
+               match = "lceil";
+       else if (str == "lceil")
+               match = "rceil";
+       else if (str == "rfloor")
+               match = "lfloor";
+       else if (str == "lfloor")
+               match = "rfloor";
+       else if (str == "rangle")
+               match = "langle";
+       else if (str == "langle")
+               match = "rangle";
+       else if (str == "llbracket")
+               match = "rrbracket";
+       else if (str == "rrbracket")
+               match = "llbracket";
+       else if (str == "backslash")
+               match = "/";
+       else if (str == "/")
+               match = "backslash";
+       else
+               return symbol;
 
        return mathSymbol(match).unicode;
 }
@@ -445,32 +495,19 @@ void GuiDelimiter::on_swapPB_clicked()
        // Convert back to QString to locate them in the widget.
        MathSymbol const & nlms = mathSymbol(texName(lc));
        MathSymbol const & nrms = mathSymbol(texName(rc));
-       QString lqs(nlms.fontcode ?
-               QChar(nlms.fontcode) : toqstr(docstring(1, nlms.unicode)));
-       QString rqs(nrms.fontcode ?
-               QChar(nrms.fontcode) : toqstr(docstring(1, nrms.unicode)));
-
-       // Handle unencoded "symbol" of "(None)".
-       if (lqs == "?")
-               lqs = qt_("(None)");
-       if(rqs == "?")
-               rqs = qt_("(None)");
 
        // Locate matching QListWidgetItem.
-       QList<QListWidgetItem *> lwi = leftLW->findItems(lqs, Qt::MatchExactly);
-       QList<QListWidgetItem *> rwi = rightLW->findItems(rqs, Qt::MatchExactly);
+       QListWidgetItem * lwi = left_list_items_[nlms.unicode];
+       QListWidgetItem * rwi = right_list_items_[nrms.unicode];
 
        // Select.
-       leftLW->setCurrentItem(lwi.first());
-       rightLW->setCurrentItem(rwi.first());
+       leftLW->setCurrentItem(lwi);
+       rightLW->setCurrentItem(rwi);
 
        updateTeXCode(sizeCO->currentIndex());
 }
 
 
-Dialog * createGuiDelimiter(GuiView & lv) { return new GuiDelimiter(lv); }
-
-
 } // namespace frontend
 } // namespace lyx