From ce7982657daa915b896ba65da3cfe1af6ba2cc49 Mon Sep 17 00:00:00 2001 From: Dou Date: Wed, 20 May 2020 02:07:07 +0200 Subject: [PATCH] Fix the bugs for issue #4 --- examples/introduction.ipynb | 53 +++++++++++++++++-- postBuild | 8 ++- requirements.txt | 1 - src/widget.ts | 26 +++++---- .../nbextension/static/extension.js | 17 ------ widget_periodictable/periodic_table.py | 36 +++++++++++-- 6 files changed, 102 insertions(+), 39 deletions(-) delete mode 100644 widget_periodictable/nbextension/static/extension.js diff --git a/examples/introduction.ipynb b/examples/introduction.ipynb index babae7b..3413a0d 100644 --- a/examples/introduction.ipynb +++ b/examples/introduction.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -19,15 +19,60 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "86fa0f86c11a4ba790f21039e977d680", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "PTableWidget(selected_colors=['red', 'green', 'yellow'], states=3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# Show the widget\n", - "widget = PTableWidget(states = 3, selected_colors = ['red', 'green', 'yellow'], noselect_color='white')\n", + "widget = PTableWidget(states = 3, selected_colors = ['red', 'green', 'yellow'], unselected_color='pink')\n", "widget" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Set the states of the elements\n", + "\n", + "The periodic table allows users to customize the states of the selected elements. \n", + "If one do not give the selected element state, it will set the state as zero." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "widget.selected_elements = [\"La\", \"Ce\", \"Pr\", \"Nd\"]\n", + "widget.set_element_state(\"Ce\", 2)\n", + "widget.set_element_state(\"Am\", 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "widget.selected_elements = [\"Ce\", \"Am\", \"Bk\", \"Cf\"]" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/postBuild b/postBuild index baf6c87..0468b5b 100644 --- a/postBuild +++ b/postBuild @@ -1,6 +1,10 @@ #!/bin/bash -jupyter labextension install @jupyter-widgets/jupyterlab-manager +jupyter labextension install @jupyter-widgets/jupyterlab-manager jupyter nbextension enable --py --sys-prefix appmode jupyter serverextension enable --py --sys-prefix appmode jupyter nbextension enable --py widgetsnbextension -jupyter lab build +pip install -e . +jlpm +jlpm run build +jupyter labextension install . +jupyter lab build diff --git a/requirements.txt b/requirements.txt index 2878d22..4930048 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ ipywidgets==7.5.0 appmode==0.6.0 IPython==7.8.0 -widget-periodictable diff --git a/src/widget.ts b/src/widget.ts index c2aaabf..c649ee5 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -88,10 +88,10 @@ class MCPTableView extends DOMWidgetView { ' noselect element-<%= elementName %><% if (selectedElements.includes(elementName) && ' + '(! disabledElements.includes(elementName)) ) { print(" elementOn"); } %>" '+ 'style="background-color: <% if (disabledElements.includes(elementName)) {print(disabledColor)}' + - 'else if (selectedElements.includes(elementName)) { i = selectedElements.indexOf(elementName); print(selectedColors[selectedStates[i]]);} else{print(noselectColor)} %>" '+ - 'title="state: <% if (selectedElements.includes(elementName)) { i = selectedElements.indexOf(elementName); print(selectedStates[i]);} '+ - 'else if (disabledElements.includes(elementName)){print("disabled");} else {print("noselcted");} %>" ><% '+ - 'print(displayNamesReplacements[elementName] || elementName); %>' + + 'else if (selectedElements.includes(elementName)) { i = selectedElements.indexOf(elementName); print(selectedColors[selectedStates[i]]);} else{print(unselectedColor)} %>" '+ + // 'title="state: <% if (selectedElements.includes(elementName)) { i = selectedElements.indexOf(elementName); print(selectedStates[i]);} '+ + // 'else if (disabledElements.includes(elementName)){print("disabled");} else {print("unselected");} %>" ><% '+ + '><% print(displayNamesReplacements[elementName] || elementName); %>' + '<% } }; print(""); } %>'); render() { @@ -168,16 +168,20 @@ class MCPTableView extends DOMWidgetView { var selectedElements = this.model.get('selected_elements'); var disabledElements = this.model.get('disabled_elements'); var disabledColor = this.model.get('disabled_color'); - var noselectColor = this.model.get('noselect_color'); + var unselectedColor = this.model.get('unselected_color'); var selectedColors = this.model.get('selected_colors'); var selectedStates = this.model.get('selected_states'); var newSelectedElements = selectedElements.slice(); var newSelectedColors = selectedColors.slice(); var newSelectedStates = selectedStates.slice(); + if (newSelectedElements.length != newSelectedStates.length){ + return; + }; + // Here I want to clean up the two elements lists, to avoid // to have unknown elements in the selectedElements, and - // to remove disabledElements from the selectedElements list. + // to remove disabled Elements from the selectedElements list. // I use s variable to check if anything changed, so I send // back the data to python only if needed @@ -186,15 +190,17 @@ class MCPTableView extends DOMWidgetView { newSelectedElements = _.difference(newSelectedElements, disabledElements); // Remove unknown elements from the selectedElements list newSelectedElements = _.intersection(newSelectedElements, elementList); + var changed = newSelectedElements.length != selectedElementsLength; // call the update (to python) only if I actually removed/changed // something if (changed) { // Make a copy before setting - while (newSelectedElements.length > newSelectedStates.length){ - newSelectedStates.push(0); - } + // while (newSelectedElements.length > newSelectedStates.length){ + // newSelectedStates.push(0); + // }; + this.model.set('selected_elements', newSelectedElements); this.model.set('selected_states', newSelectedStates); this.touch(); @@ -208,7 +214,7 @@ class MCPTableView extends DOMWidgetView { selectedElements: newSelectedElements, disabledElements: disabledElements, disabledColor: disabledColor, - noselectColor: noselectColor, + unselectedColor: unselectedColor, selectedColors: newSelectedColors, selectedStates: newSelectedStates }) + diff --git a/widget_periodictable/nbextension/static/extension.js b/widget_periodictable/nbextension/static/extension.js deleted file mode 100644 index 296acbd..0000000 --- a/widget_periodictable/nbextension/static/extension.js +++ /dev/null @@ -1,17 +0,0 @@ -// Entry point for the notebook bundle containing custom model definitions. -// -define(function() { - "use strict"; - - window['requirejs'].config({ - map: { - '*': { - 'widget-periodictable': 'nbextensions/widget_periodictable/index', - }, - } - }); - // Export the required load_ipython_extension function - return { - load_ipython_extension : function() {} - }; -}); diff --git a/widget_periodictable/periodic_table.py b/widget_periodictable/periodic_table.py index 1248d91..da1af57 100644 --- a/widget_periodictable/periodic_table.py +++ b/widget_periodictable/periodic_table.py @@ -9,8 +9,9 @@ """ from ipywidgets import DOMWidget -from traitlets import Unicode, Int, List, Dict +from traitlets import Unicode, Int, List, Dict, observe from ._frontend import module_name, module_version +from copy import deepcopy class PTableWidget(DOMWidget): """TODO: Add docstring here @@ -25,21 +26,22 @@ class PTableWidget(DOMWidget): disabled_elements = List([]).tag(sync=True) display_names_replacements = Dict({}).tag(sync=True) disabled_color = Unicode('gray').tag(sync=True) - noselect_color = Unicode('pink').tag(sync=True) + unselected_color = Unicode('pink').tag(sync=True) states = Int(1).tag(sync=True) selected_states = List([]).tag(sync=True) selected_colors = List([]).tag(sync=True) - def __init__(self, states = 1, disabled_color = 'gray', noselect_color = 'pink', selected_colors = ["#a6cee3", "#b2df8a", "#fdbf6f", "#6a3d9a", "#b15928", "#e31a1c", "#1f78b4", "#33a02c", "#ff7f00", "#cab2d6", "#ffff99"]): + def __init__(self, states = 1, disabled_color = 'gray', unselected_color = 'pink', selected_colors = ["#a6cee3", "#b2df8a", "#fdbf6f", "#6a3d9a", "#b15928", "#e31a1c", "#1f78b4", "#33a02c", "#ff7f00", "#cab2d6", "#ffff99"]): super(PTableWidget, self).__init__() self.states = states self.disabled_color = disabled_color - self.noselect_color = noselect_color + self.unselected_color = unselected_color self.selected_colors = selected_colors if len(selected_colors) < states: - self.selected_colors = selected_colors + ["#a6cee3", "#b2df8a", "#fdbf6f", "#6a3d9a", "#b15928", "#e31a1c", "#1f78b4", "#33a02c", "#ff7f00", "#cab2d6", "#ffff99"] + additional_colors = ["#a6cee3", "#b2df8a", "#fdbf6f", "#6a3d9a", "#b15928", "#e31a1c", "#1f78b4", "#33a02c", "#ff7f00", "#cab2d6", "#ffff99"] + self.selected_colors = selected_colors + additional_colors * (1 + (states - len(selected_colors)) // len(additional_colors)) def get_elements_by_state(self, state): x = []; @@ -47,3 +49,27 @@ def get_elements_by_state(self, state): if j == state: x.append(self.selected_elements[i]) return x + + def set_element_state(self, elementName, state): + if state < self.states: + if elementName in self.selected_elements: + i = self.selected_elements.index(elementName); + states = deepcopy(self.selected_states); + states[i] = state; + self.selected_states = states; + else: + self.selected_elements = self.selected_elements + [elementName] + self.set_element_state(elementName, state) + + @observe('selected_elements') + def _selected_elements_changed(self, change): + x = []; + y = []; + for i in change["new"]: + if i in change["old"]: + x.append(i) + y.append(self.selected_states[change["old"].index(i)]) + else: + x.append(i) + y.append(0) + self.selected_states = y