Another Change

Click ‘+’ at the bottom, a new selector and a new style element. So each selector was added to a new style element. The change is a single style element should be there for each file and thus it can have multiple selectors. Both the earlier version and new implementation are shown below:

Screenshot from 2016-06-15 00:25:12

Screenshot from 2016-06-15 00:27:37

Setting the selectors in single style element when the dialog is to be populated with selectors from already existing drawing is in progress yet. More on previous implementation of populating the style dialog can be seen here.

Besides this implementation, I have added buttons to the treeview against each row containing selector. These ‘+’ buttons will be used to add selected objects to existing selectors instead of creating a new one every time, as per need of the user.

Class Attribute Also Set

And class attribute is also back. Initially, when I started with addition of a style selector, I was adding the selector names to class attribute of the selected object. Whether it was the object’s id or a class name, both went to class attribute’s value. But since style element is the focus, that work was discarded.

In the current scenario, it has to be checked that the selector being added is a class or an ID. In case it is a class, the class attribute of the object has to be set. If class attribute already has a value, the new class value is appended to the previous one (no replacement of previous one).

I cleverly erased the dot from beginning of the selector name since class value = selector name without any dots. Dots are just a representation that the selector associated with them is a class selector. This was another issue addressed on June 13.

Passing a test

Getting a test file from Tavmjong Bah, which my code didn’t pass, I made a few changes in my code.

First issue was the map containing keys and values of selectors returned empty keys. So the parsing of the style element had to be changed. Using the delimiters { and }, I fixed the issue and my code passed the test file.

Previously, I didn’t check if the style attribute of the object existed or not. In case it did not, a crash occurred. The following line of code caused the issue.

std::string style = std::string(obj->getRepr()->attribute("style"));

Further I used this style to set the selector value to be added to style element which caused the crash since value had nothing. And for the case when an object had no style attribute and it was added to a style selector, I created a style attribute for the object with empty value which is acceptable.

Just deletion from treeview

Moving on from adding a selector to the style dialog, my next step is to delete a selector from the selector as well as from the XML representation of the document. Following the approach to get the selection from the treeview, get_selection() is used to obtain the selected row which is then iterated using get_selected().

If the iterator exists, the corresponding row is deleted from the treeview using erase(). Deletion from XML representation is challenging. I tokenized the selector value altogether and compared the first token which is the name of the selector to the selector selected in treeview. If these two are equal, then the corresponding style node is deleted from XML representation.

However, I ended up in a crash of Inkscape while deleting the style node, so currently all it deletes is the row from treeview.

Style Dialog Populated with Classes & IDs

Today I added classes and ids to style dialog distinguished by characters ‘#’ and ‘.’ respectively. If the selector name is the object’s id, it is added to the dialog as #object-id. If the user wishes to add a class as a selector, it is added to the dialog as .red.

Screenshot from 2016-06-10 22:22:27

Another implementation I did today includes populating the style dialog with existing selectors in the style sheet. Whenever a style element is created, it is pushed to a map whose key is the selector’s name and value includes style properties in the selector. This map is iterated to obtain the selectors from the document that is opened. The selectors are presented in the style dialog. The user thus knows the list of selectors already available in the document.

Screenshot from 2016-06-10 22:25:49

A Step Back & Ahead

Well adding selector to class seemed pretty easy, eh? I was feeling pretty accomplished unless I became aware I am heading not towards the target. Yesterday morning, I was told that selector was not to be added to the class attribute and rather to style attribute to the object. And this messy head confused style element with style attribute.

Selectors should be a part of style element and not style attribute. After spending entire June 8 playing and making it almost work with style attribute and moving to style element today, things seem to be working to some extent. Yes, on clicking the + at bottom of style dialog, the text in entry box is written as selector to style element. A new style element is created on a click on + of the form shown below:

Screenshot from 2016-06-09 23:04:00

Making use of attributeList() to get the style properties posed a challenge in itself, it kept returning a 0 or a 1 and no attributes. Finally iterated them using List<AttributeRecord> to get only the style property’s value and then suffixing it to the selector name gave me what is visible in the style element in the picture above.

Next I used createElement() to create a node svg:style. The content is set using createTextNode() and adding it to the svg:style element. While writing this, I encountered the issue: parsing error: 1:0:could not recognize next production, solved it by enclosing the content value in braces {}.

Currently, I am working on a map, that maps a selector’s name to style properties. Using this map will help in selection of objects corresponding to a selector and vice-versa. Any manipulation to this map will also keep the stylesheet updated.

Also using this map, I am trying to populate the treeview, whenever a stylesheet with some selectors entailed is opened, with the selecotor names available.

Setting text of entry box

The text in the entry box (the one in the dialog that opens up on clicking ‘+’ at the bottom of style dialog) determines the value of ‘class’ attribute of an object. A default text value shows up in the dialog box if no object is selected in the drawing.

Screenshot from 2016-06-07 00:14:38

In case, one object is selected, by default its id shows up in the text dialog. The user can change this text if he/she wishes.
Screenshot from 2016-06-07 00:15:35

However, if two or more objects are selected, then the text value in the entry box contains id of each of the selected objects separated by a space. In all the cases, clicking ‘Add’ adds a new selector to the treeview.
Screenshot from 2016-06-07 00:20:00

Also if some selection exists, then the class attribute of the object is set with value equal to text in the entry box. If class attribute for an object already has a value, then the new value added by the user is appended to the existing one.

_setClassAttribute(std::vector<spobject *>) is used to append the values in case multiple objects are selected. This function is called when text in the entry box has to be set up.

A dialog box opens on ‘+’

First thing being adding a selector to the treeview by clicking on ‘+’ at the bottom, the signal emitted by clicking the button was connected to a function, its so called slot. Clicking this button now opens up a dialog box which contains an entry box in it.

Entry box is a single line text edit field. Adding it to the dialog box posed issues like:

Gtk-WARNING **: Attempting to add a widget with type gtkmmGtkEntry to a gtkmmGtkDialog, but as a GtkBin subclass a gtkmm__GtkDialog can only contain one widget at a time; it already contains a widget of type GtkVBox

I added a Gtk::VBox to the dialog, then added the entry box to this vertical box and I got the warning emphasized above. Nothing showed up in the dialog box. Empty. After struggling quite some time to solve this issue, I studied the source file of Dialog class. Some answers online showed usage of get_content_area() which however does not exist for the Dialog class now.

Studying its source file, the cause of the warning showed up. getVBox() is a function of the Dialog class, entailing the fact that it already has one. Solved the issue and added entry widget to the dialog. Besides, I added a button clicking which a selector with name equal to text in entry box will be added to the treeview of the style dialog.

Screenshot from 2016-06-06 23:39:26

Adding UI components to Style Dialog

The list of UI components to be added to the style dialog include:

  • A treeView to display the list of selectors.
  • A button to add a new selector to the list of selectors
  • A button to delete selector from the selectors’ list

The buttons have been added to a HBox _buttonBox which is further contained in a bigger VBox _mainbox in the dialog. The _mainBox contains both the treeview and the HBox containing the two buttons to add and delete selectors. Currently, I have disabled the delete button, keeping my focus on functionality to add selector.

Lack of documentation of gtkmm was not very helpful. I faced some issues which I was unable to solve initially. Since Inkscape is migrating to Gtk+ 3, so I developed the UI components using Gtk+ instead of gtkmm. But the long term goal of Inkscape’s development cycle involves migrating to gtkmm completely, so as guided by mentor Tavmjong Bah, I moved back to gtkmm.

Some of the issues I confronted include:

  1. Button size expanded as I changed the size of the dialog. In the correct case, it should have remained standard. Using the appropriate flag from the enum Gtk::PackOptions, I was able to fix it.
  2. On adding the treeview to the dialog, empty space appeared at the top in the widget. Using the pack_start() function with appropriate packing options, all options available, this is not fixed yet.

Screenshot from 2016-06-04 22:13:55

Registering Style Dialog

For enhancing CSS support in Inkscape, a Style Dialog is being developed for selection of different objects on the basis of their various style attributes. Initiating with the creation of the Style Dialog, the first step was to register the new dialog in the application.

Verbs (generally called commands) are added to verbs.h in the project. They allow implementing functionality via use of menu items. For the style dialog, I added SP_VERB_DIALOG_STYLE to verbs.h. After this, the action corresponding to the newly added verb has to be defined.

Different classes for different types of verbs have been created in verbs.cpp. Corresponding to the DialogVerb class, the function perform(SPAction action, void data) is referred to add a new case for the verb SP_VERB_DIALOG_STYLE.

case SP_VERB_DIALOG_STYLE:
dt->_dlg_mgr->showDialog("Style");
break;

This shows up the Style Dialog when the corresponding verb is activated in the constructor of StyleDialog class. dt which is a pointer of SPDesktop class is the current desktop of the application where dialog will show up.

Next the verb must be added to the table of statically created verbs. The following line is added to _base_verbs[].

new DialogVerb(SP_VERB_DIALOGSTYLE, "DialogStyle", N("Style Dialog..."), N_("View Style Dialog"), NULL),

Lastly, the dialog should be registered in dialog-manager.cpp. Associating the dialog to both dockable and floating behavior, it is registered in the factory as follows:
registerFactory("StyleDialog", &create<StyleDialog, FloatingBehavior>);
registerFactory("StyleDialog", &create<StyleDialog, DockBehavior>);

Screenshot from 2016-06-04 14:17:21

Also since I wanted to add the Style Dialog option to Object menu, so in menu-skeleton, I added it under the Object Option using:

<verb verb-id=\"DialogStyle\" />\n"

Screenshot from 2016-06-04 14:14:41

This registered an empty Style Dialog in the Inkscape with an option in submenu for the dialog.