Add some UI to easily insert mathematical symbols into the LaTeX input box

RESOLVED FIXED in seamonkey2.34

Status

SeaMonkey
Composer
RESOLVED FIXED
4 years ago
4 years ago

People

(Reporter: fredw, Assigned: fredw)

Tracking

Trunk
seamonkey2.34
Dependency tree / graph

SeaMonkey Tracking Flags

(seamonkey2.34 fixed)

Details

Attachments

(1 attachment, 6 obsolete attachments)

(Assignee)

Description

4 years ago
One of the difficulty for people to enter math expressions is to remember all the LaTeX commands to insert mathematical symbols. Since TeXZilla supports Unicode input, we could just organize all or part of the following math Unicode characters

https://github.com/fred-wang/TeXZilla/wiki/TeXZilla-Commands#identifiers
https://github.com/fred-wang/TeXZilla/wiki/TeXZilla-Commands#operators

into some categories ; and create the corresponding buttons to insert them.
(Assignee)

Updated

4 years ago
Summary: Add some UI to easily insert mathematical symbols in the LaTeX input box → Add some UI to easily insert mathematical symbols into the LaTeX input box
(Assignee)

Comment 1

4 years ago
Created attachment 8499401 [details] [diff] [review]
Patch V1

OK, I just wrote a very basic patch as a proof-of-concept.

This does not handle surrogate pairs and does not implement a way to switch between several categories.
(Assignee)

Comment 2

4 years ago
Created attachment 8499403 [details]
screenshot_insertMath.png
(Assignee)

Comment 3

4 years ago
Created attachment 8507499 [details] [diff] [review]
Patch V2

This organizes symbols with tabpanels and handles surrogate pairs.

However for some reason I can not click on a button with the mouse and I have to use the keyboard instead. (example https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/tabbox#Examples works, though).
Attachment #8499401 - Attachment is obsolete: true
Attachment #8507499 - Flags: feedback?(neil)

Comment 4

4 years ago
Comment on attachment 8507499 [details] [diff] [review]
Patch V2

>+  var selectionStart = gDialog.input.selectionStart;
>+  gDialog.input.value =
>+    gDialog.input.value.substring(0, selectionStart) + aChar +
>+    gDialog.input.value.substring(gDialog.input.selectionEnd);
>+  gDialog.input.selectionStart = selectionStart + aChar.length;
>+  gDialog.input.selectionEnd = gDialog.input.selectionStart;
I think you can use
gDialog.input.editor.QueryInterface(Components.interfaces.nsIPlaintextEditor).insertText(aChar);

>+  gDialog.input.focus();
>+  updateMath();
[Possibly if you focus the input first it will also trigger the input handler for you.]

>+  for (var i = 0; i < aSymbolPanelList.length; i++) {
>+
>+    // Create a <rows> element with the symbols of the i-th panel.
>+    var symbols = aSymbolPanelList[i];
If you don't use i again you can write for (var symbols of aSymbolPanelList)

>+    var rows = document.createElementNS(XULNS, "rows");
Don't need this because you create it again immediately anyway.

>+    var row, j, k, columnCount = 13;
>+    var tabLabel = "", tabLabelLength = 3;
Two of these should be const.

>+    for (j = 0, k = 0; j < symbols.length; j++, k++) {
I think you can use for (var symbol of symbols) which also handles surrogates. (You'd still have to count the columns yourself though.)

>+      button.setAttribute("class", "checkbox-spacer");
This isn't what this class is designed for sorry. Maybe what you really need is <toolbarbutton class="tabbable">.

>+      button.setAttribute("oncommand", "insertSymbol('" + symbol + "')");
One event listener to rule them all: <tabpanels oncommand="insertSymbol(event.target.label);"/>

>+      columns.appendChild(document.createElementNS(XULNS, "column"));
Add flex="1" to all the columns so that the buttons will space out evenly on each tab. (Needs "tabpanel" fix below.)

>+    // Create the <grid> element with the <rows> and <columns> children.
>+    var grid = document.createElementNS(XULNS, "grid");
>+    grid.appendChild(rows);
>+    grid.appendChild(columns);
Appending the columns last puts them above the rows in the z-order. Put the rows last to fix this and make the buttons clickable.

>+    // Create a new <tab> element with the label determined above.
>+    var tab = document.createElementNS(XULNS, "tab");
>+    tab.setAttribute("label", tabLabel);
>+    tabbox.tabs.appendChild(tab);
(This messes up the tabbox's idea of the initially selected tab.)

>+    // Create a new <tabpanel> containing the <grid>.
>+    var tabpanel = document.createElementNS(XULNS, "tabpanel");
>+    tabpanel.appendChild(grid);
>+    tabbox.tabpanels.appendChild(tabpanel);
No such thing as a tabpanel. Just append the grid directly.
Attachment #8507499 - Flags: feedback?(neil)
(Assignee)

Comment 5

4 years ago
Created attachment 8509042 [details] [diff] [review]
Patch V3

> >+    var rows = document.createElementNS(XULNS, "rows");
> Don't need this because you create it again immediately anyway.

I didn't understand that one.

> (This messes up the tabbox's idea of the initially selected tab.)

I removed the attribute. Not sure how to force the tab to be selected. But anyway that does not change the panel initially displayed.
Attachment #8499403 - Attachment is obsolete: true
Attachment #8507499 - Attachment is obsolete: true
Attachment #8509042 - Flags: feedback?
(Assignee)

Updated

4 years ago
Attachment #8509042 - Attachment description: texzilla-unicode-input.patch → Patch V3
(Assignee)

Updated

4 years ago
Attachment #8509042 - Flags: feedback? → feedback?(neil)

Comment 6

4 years ago
Comment on attachment 8509042 [details] [diff] [review]
Patch V3

>+    for (var symbol of symbols) {
>+      var row;
Nit: declaring row looks odd here, since you retain its value between loop iterations. Might be more readable to declare it just before instead.

>+    // Create a <columns> element with the desired number of columns.
>+    var columns = document.createElementNS(XULNS, "columns");
>+    for (i = 0; i < columnCount; i++) {
>+      var column = document.createElementNS(XULNS, "column");
>+      column.setAttribute("flex", "1");
This almost does what I want but the various symbols are slightly different widths so that the columns don't quite distribute evenly. I'd appreciate it if you could fix this by setting the width to 1 too. (The flex then calculates the column width by flexing this width rather than the actual character widths.)

>+    // Append the new tab panel.
>+    tabbox.tabpanels.appendChild(grid);
>+  }
It would be helpful if you set the tabbox's selectedIndex to 0 when you finished, so that the tab looks selected.

>+    <tabpanels oncommand="insertSymbol(event.target.label)"/>
Nit: event handlers are JS statements so should end with a semicolon.

The only other problem I have with this is that there is nothing to label the tabbox. This might not be a problem if you move it above the options. The example also looks a bit lost there, I don't know whether it would be possible to make it placeholder text instead.
Attachment #8509042 - Flags: feedback?(neil) → feedback+
(Assignee)

Comment 7

4 years ago
Created attachment 8510861 [details] [diff] [review]
Patch V4
Attachment #8509042 - Attachment is obsolete: true
(Assignee)

Comment 8

4 years ago
(In reply to neil@parkwaycc.co.uk from comment #6)
> >+    // Create a <columns> element with the desired number of columns.
> >+    var columns = document.createElementNS(XULNS, "columns");
> >+    for (i = 0; i < columnCount; i++) {
> >+      var column = document.createElementNS(XULNS, "column");
> >+      column.setAttribute("flex", "1");
> This almost does what I want but the various symbols are slightly different
> widths so that the columns don't quite distribute evenly. I'd appreciate it
> if you could fix this by setting the width to 1 too. (The flex then
> calculates the column width by flexing this width rather than the actual
> character widths.)

The problem with this is that the label of the largest buttons become "...", unless we increase the window width.

> 
> >+    // Append the new tab panel.
> >+    tabbox.tabpanels.appendChild(grid);
> >+  }
> It would be helpful if you set the tabbox's selectedIndex to 0 when you
> finished, so that the tab looks selected.

OK, for some reason tabbox.setAttribute("selectedIndex", "0") does not work but tabbox.selectedIndex = 0; does.

> The only other problem I have with this is that there is nothing to label
> the tabbox. This might not be a problem if you move it above the options.
> The example also looks a bit lost there, I don't know whether it would be
> possible to make it placeholder text instead.

I tried to do something. Let me know if that looks better.
Flags: needinfo?(neil)

Comment 9

4 years ago
(In reply to Frédéric Wang from comment #8)
> (In reply to comment #6)
> > >+    // Create a <columns> element with the desired number of columns.
> > >+    var columns = document.createElementNS(XULNS, "columns");
> > >+    for (i = 0; i < columnCount; i++) {
> > >+      var column = document.createElementNS(XULNS, "column");
> > >+      column.setAttribute("flex", "1");
> > This almost does what I want but the various symbols are slightly different
> > widths so that the columns don't quite distribute evenly. I'd appreciate it
> > if you could fix this by setting the width to 1 too. (The flex then
> > calculates the column width by flexing this width rather than the actual
> > character widths.)
> 
> The problem with this is that the label of the largest buttons become "...",
> unless we increase the window width.

Ah, must depend on your OS's fonts I guess. Thanks for trying.

> for some reason tabbox.setAttribute("selectedIndex", "0") does not work
> but tabbox.selectedIndex = 0; does.
Yes, it sets up some other attributes to make everything look right.

> > The only other problem I have with this is that there is nothing to label
> > the tabbox. This might not be a problem if you move it above the options.
> > The example also looks a bit lost there, I don't know whether it would be
> > possible to make it placeholder text instead.
> 
> I tried to do something. Let me know if that looks better.
Cool! Just one code nit:
>+    var input = gDialog.input.value;
>+    if (!input) {
>+      input = gDialog.input.placeholder;
var input = gDialog.input.value || gDialog.input.placeholder;
Flags: needinfo?(neil)
(Assignee)

Comment 10

4 years ago
(In reply to neil@parkwaycc.co.uk from comment #9)
> Cool! Just one code nit:
> >+    var input = gDialog.input.value;
> >+    if (!input) {
> >+      input = gDialog.input.placeholder;
> var input = gDialog.input.value || gDialog.input.placeholder;

argh! I initially did that but I thought you won't be happy to use boolean operators for strings. I'll put that back.
(Assignee)

Comment 11

4 years ago
Created attachment 8511259 [details] [diff] [review]
Patch V5
Attachment #8510861 - Attachment is obsolete: true
Attachment #8511259 - Flags: review?(neil)
Comment on attachment 8511259 [details] [diff] [review]
Patch V5

Sorry for the delay.
Attachment #8511259 - Flags: review?(neil) → review+
(Assignee)

Comment 13

4 years ago
Created attachment 8522022 [details] [diff] [review]
Patch final version

Just adding r=neil to the commit message.
Attachment #8511259 - Attachment is obsolete: true
(Assignee)

Updated

4 years ago
Keywords: checkin-needed
(Assignee)

Updated

4 years ago
Blocks: 1098150
(Assignee)

Comment 14

4 years ago
Can someone please commit this patch?
Flags: needinfo?(philip.chee)

Comment 15

4 years ago
(In reply to Frédéric Wang (:fredw) from comment #14)
> Can someone please commit this patch?
The tree is closed due to multiple bustages. I'll check it in once the Thunderbird tree re-opens.

Comment 16

4 years ago
Pushed to comm-central:
http://hg.mozilla.org/comm-central/rev/d04571dd1bf4
Status: NEW → RESOLVED
Last Resolved: 4 years ago
status-seamonkey2.34: --- → fixed
Keywords: checkin-needed
Resolution: --- → FIXED
Target Milestone: --- → seamonkey2.34

Updated

4 years ago
Flags: needinfo?(philip.chee)
(Assignee)

Comment 17

4 years ago
Thanks Philip!

Updated

4 years ago
Blocks: 1113572
You need to log in before you can comment on or make changes to this bug.