Commit 3276773e authored by sumpfralle's avatar sumpfralle

replaced "register_parameter_section" with a normal ui_section


git-svn-id: https://pycam.svn.sourceforge.net/svnroot/pycam/trunk@1181 bbaffbd6-741e-11dd-a85d-61de82d9cad9
parent ed7f47eb
...@@ -20,7 +20,9 @@ You should have received a copy of the GNU General Public License ...@@ -20,7 +20,9 @@ You should have received a copy of the GNU General Public License
along with PyCAM. If not, see <http://www.gnu.org/licenses/>. along with PyCAM. If not, see <http://www.gnu.org/licenses/>.
""" """
# gtk and gobject are imported later (to avoid plugin load failures)
import gtk
import gobject
import pycam.Utils.log import pycam.Utils.log
...@@ -69,7 +71,6 @@ class InputNumber(InputBaseClass): ...@@ -69,7 +71,6 @@ class InputNumber(InputBaseClass):
def __init__(self, digits=0, start=0, lower=0, upper=100, def __init__(self, digits=0, start=0, lower=0, upper=100,
increment=1, change_handler=None): increment=1, change_handler=None):
import gtk
adjustment = gtk.Adjustment(value=start, lower=lower, upper=upper, adjustment = gtk.Adjustment(value=start, lower=lower, upper=upper,
step_incr=increment) step_incr=increment)
self.control = gtk.SpinButton(adjustment, digits=digits) self.control = gtk.SpinButton(adjustment, digits=digits)
...@@ -89,8 +90,6 @@ class InputNumber(InputBaseClass): ...@@ -89,8 +90,6 @@ class InputNumber(InputBaseClass):
class InputChoice(InputBaseClass): class InputChoice(InputBaseClass):
def __init__(self, choices, change_handler=None): def __init__(self, choices, change_handler=None):
import gtk
import gobject
self.model = gtk.ListStore(gobject.TYPE_STRING) self.model = gtk.ListStore(gobject.TYPE_STRING)
self._values = [] self._values = []
for label, value in choices: for label, value in choices:
...@@ -149,8 +148,6 @@ class InputChoice(InputBaseClass): ...@@ -149,8 +148,6 @@ class InputChoice(InputBaseClass):
class InputTable(InputChoice): class InputTable(InputChoice):
def __init__(self, choices, change_handler=None): def __init__(self, choices, change_handler=None):
import gtk
import gobject
self.model = gtk.ListStore(gobject.TYPE_STRING) self.model = gtk.ListStore(gobject.TYPE_STRING)
self._values = [] self._values = []
for label, value in choices: for label, value in choices:
...@@ -191,7 +188,6 @@ class InputTable(InputChoice): ...@@ -191,7 +188,6 @@ class InputTable(InputChoice):
class InputCheckBox(InputBaseClass): class InputCheckBox(InputBaseClass):
def __init__(self, start=False, change_handler=None): def __init__(self, start=False, change_handler=None):
import gtk
self.control = gtk.CheckButton() self.control = gtk.CheckButton()
self.control.set_active(start) self.control.set_active(start)
if change_handler: if change_handler:
...@@ -205,3 +201,81 @@ class InputCheckBox(InputBaseClass): ...@@ -205,3 +201,81 @@ class InputCheckBox(InputBaseClass):
def set_value(self, value): def set_value(self, value):
self.control.set_active(value) self.control.set_active(value)
class ParameterSection(object):
def __init__(self):
self._widgets = []
self._table = gtk.Table(rows=1, columns=2)
self._table.set_col_spacings(3)
self._table.set_row_spacings(3)
self.update_widgets()
self._update_widgets_visibility()
self._table.show()
self.widget = self._table
def add_widget(self, widget, label, weight=100):
item = (widget, label, weight, [])
self._widgets.append(item)
for signal in ("hide", "show"):
item[3].append(widget.connect(signal,
self._update_widgets_visibility))
self.update_widgets()
def clear_widgets(self):
while self._widgets:
item = self._widgets.pop()
for signal_handler in item[3]:
item[0].disconnect(signal_handler)
self.update_widgets()
def update_widgets(self):
widgets = list(self._widgets)
widgets.sort(key=lambda item: item[2])
# remove all widgets from the table
for child in self._table.get_children():
self._table.remove(child)
# add the current controls
for index, widget in enumerate(widgets):
if hasattr(widget, "get_label"):
# checkbox
widget.set_label(widget[1])
self._table.attach(widget, 0, 2, index, index + 1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
elif not widget[1]:
self._table.attach(widget[0], 0, 2, index, index + 1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
else:
# spinbutton, combobox, ...
label = gtk.Label("%s:" % widget[1])
label.set_alignment(0.0, 0.5)
self._table.attach(label, 0, 1, index, index + 1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
self._table.attach(widget[0], 1, 2, index, index + 1,
xoptions=gtk.FILL, yoptions=gtk.FILL)
self._update_widgets_visibility()
def _get_table_row_of_widget(self, widget):
for child in self._table.get_children():
if child is widget:
return self._get_child_row(child)
else:
return -1
def _get_child_row(self, widget):
return gtk.Container.child_get_property(self._table, widget,
"top-attach")
def _update_widgets_visibility(self, widget=None):
for widget in self._widgets:
table_row = self._get_table_row_of_widget(widget[0])
is_visible = widget[0].props.visible
for child in self._table.get_children():
if widget == child:
continue
if self._get_child_row(child) == table_row:
if is_visible:
child.show()
else:
child.hide()
This diff is collapsed.
This diff is collapsed.
...@@ -70,10 +70,11 @@ class Processes(pycam.Plugins.ListPluginBase): ...@@ -70,10 +70,11 @@ class Processes(pycam.Plugins.ListPluginBase):
changed_set_event="process-strategy-changed", changed_set_event="process-strategy-changed",
changed_set_list_event="process-strategy-list-changed", changed_set_list_event="process-strategy-list-changed",
get_current_set_func=self._get_strategy) get_current_set_func=self._get_strategy)
parameter_widget = self.core.get("register_parameter_section")( parameter_widget = pycam.Gui.ControlsGTK.ParameterSection()
"process", "pathgenerator") self.core.register_ui_section("process_path_parameters",
parameter_widget.add_widget, parameter_widget.clear_widgets)
self.core.register_ui("process_parameters", "Path parameters", self.core.register_ui("process_parameters", "Path parameters",
parameter_widget, weight=10) parameter_widget.widget, weight=10)
self._gtk_handlers.append((self._modelview.get_selection(), self._gtk_handlers.append((self._modelview.get_selection(),
"changed", "process-selection-changed")) "changed", "process-selection-changed"))
self._gtk_handlers.append((self.gui.get_object("NameCell"), self._gtk_handlers.append((self.gui.get_object("NameCell"),
......
...@@ -31,19 +31,20 @@ class TaskParamCollisionModels(pycam.Plugins.PluginBase): ...@@ -31,19 +31,20 @@ class TaskParamCollisionModels(pycam.Plugins.PluginBase):
CATEGORIES = ["Model", "Task", "Parameter"] CATEGORIES = ["Model", "Task", "Parameter"]
def setup(self): def setup(self):
self.input_control = pycam.Gui.ControlsGTK.InputTable([], self.control = pycam.Gui.ControlsGTK.InputTable([],
change_handler=lambda widget=None: \ change_handler=lambda widget=None: \
self.core.emit_event("task-changed")) self.core.emit_event("task-changed"))
self.input_control.get_widget().set_size_request(240, -1) self.control.get_widget().set_size_request(240, -1)
self.core.get("register_parameter")("task", "models", self.core.get("register_parameter")("task", "collision_models",
"collision_models", "", self.input_control, self.control)
self.core.register_ui("task_models", "", self.control.get_widget(),
weight=5) weight=5)
self.core.register_event("model-list-changed", self._update_models) self.core.register_event("model-list-changed", self._update_models)
return True return True
def teardown(self): def teardown(self):
self.core.get("unregister_parameter")("task", "models", self.core.get("unregister_parameter")("task", "collision_models")
"collision_models") self.core.unregister_ui("task_models", self.control.get_widget())
self.core.unregister_event("model-list-changed", self._update_models) self.core.unregister_event("model-list-changed", self._update_models)
def _update_models(self): def _update_models(self):
...@@ -52,7 +53,7 @@ class TaskParamCollisionModels(pycam.Plugins.PluginBase): ...@@ -52,7 +53,7 @@ class TaskParamCollisionModels(pycam.Plugins.PluginBase):
for model in models: for model in models:
if hasattr(model, "triangles"): if hasattr(model, "triangles"):
choices.append((models.get_attr(model, "name"), model)) choices.append((models.get_attr(model, "name"), model))
self.input_control.update_choices(choices) self.control.update_choices(choices)
class TaskParamTool(pycam.Plugins.PluginBase): class TaskParamTool(pycam.Plugins.PluginBase):
...@@ -61,16 +62,18 @@ class TaskParamTool(pycam.Plugins.PluginBase): ...@@ -61,16 +62,18 @@ class TaskParamTool(pycam.Plugins.PluginBase):
CATEGORIES = ["Tool", "Task", "Parameter"] CATEGORIES = ["Tool", "Task", "Parameter"]
def setup(self): def setup(self):
self.input_control = pycam.Gui.ControlsGTK.InputChoice([], self.control = pycam.Gui.ControlsGTK.InputChoice([],
change_handler=lambda widget=None: \ change_handler=lambda widget=None: \
self.core.emit_event("task-changed")) self.core.emit_event("task-changed"))
self.core.get("register_parameter")("task", "components", "tool", self.core.get("register_parameter")("task", "tool", self.control)
"Tool", self.input_control, weight=10) self.core.register_ui("task_components", "Tool",
self.control.get_widget(), weight=10)
self.core.register_event("tool-list-changed", self._update_tools) self.core.register_event("tool-list-changed", self._update_tools)
return True return True
def teardown(self): def teardown(self):
self.core.get("unregister_parameter")("task", "components", "tool") self.core.get("unregister_parameter")("task", "tool")
self.core.unregister_ui("task_models", self.control.get_widget())
self.core.unregister_event("tool-list-changed", self._update_tools) self.core.unregister_event("tool-list-changed", self._update_tools)
def _update_tools(self): def _update_tools(self):
...@@ -78,7 +81,7 @@ class TaskParamTool(pycam.Plugins.PluginBase): ...@@ -78,7 +81,7 @@ class TaskParamTool(pycam.Plugins.PluginBase):
tools = self.core.get("tools") tools = self.core.get("tools")
for tool in tools: for tool in tools:
choices.append((tools.get_attr(tool, "name"), tool)) choices.append((tools.get_attr(tool, "name"), tool))
self.input_control.update_choices(choices) self.control.update_choices(choices)
class TaskParamProcess(pycam.Plugins.PluginBase): class TaskParamProcess(pycam.Plugins.PluginBase):
...@@ -87,16 +90,18 @@ class TaskParamProcess(pycam.Plugins.PluginBase): ...@@ -87,16 +90,18 @@ class TaskParamProcess(pycam.Plugins.PluginBase):
CATEGORIES = ["Process", "Task", "Parameter"] CATEGORIES = ["Process", "Task", "Parameter"]
def setup(self): def setup(self):
self.input_control = pycam.Gui.ControlsGTK.InputChoice([], self.control = pycam.Gui.ControlsGTK.InputChoice([],
change_handler=lambda widget=None: \ change_handler=lambda widget=None: \
self.core.emit_event("task-changed")) self.core.emit_event("task-changed"))
self.core.get("register_parameter")("task", "components", "process", self.core.get("register_parameter")("task", "process", self.control)
"Process", self.input_control, weight=20) self.core.register_ui("task_components", "Process",
self.control.get_widget(), weight=20)
self.core.register_event("process-list-changed", self._update_processes) self.core.register_event("process-list-changed", self._update_processes)
return True return True
def teardown(self): def teardown(self):
self.core.get("unregister_parameter")("task", "components", "process") self.core.get("unregister_parameter")("task", "process")
self.core.unregister_ui("task_models", self.control.get_widget())
self.core.unregister_event("process-list-changed", self._update_processes) self.core.unregister_event("process-list-changed", self._update_processes)
def _update_processes(self): def _update_processes(self):
...@@ -104,7 +109,7 @@ class TaskParamProcess(pycam.Plugins.PluginBase): ...@@ -104,7 +109,7 @@ class TaskParamProcess(pycam.Plugins.PluginBase):
processes = self.core.get("processes") processes = self.core.get("processes")
for process in processes: for process in processes:
choices.append((processes.get_attr(process, "name"), process)) choices.append((processes.get_attr(process, "name"), process))
self.input_control.update_choices(choices) self.control.update_choices(choices)
class TaskParamBounds(pycam.Plugins.PluginBase): class TaskParamBounds(pycam.Plugins.PluginBase):
...@@ -113,16 +118,18 @@ class TaskParamBounds(pycam.Plugins.PluginBase): ...@@ -113,16 +118,18 @@ class TaskParamBounds(pycam.Plugins.PluginBase):
CATEGORIES = ["Bounds", "Task", "Parameter"] CATEGORIES = ["Bounds", "Task", "Parameter"]
def setup(self): def setup(self):
self.input_control = pycam.Gui.ControlsGTK.InputChoice([], self.control = pycam.Gui.ControlsGTK.InputChoice([],
change_handler=lambda widget=None: \ change_handler=lambda widget=None: \
self.core.emit_event("task-changed")) self.core.emit_event("task-changed"))
self.core.get("register_parameter")("task", "components", "bounds", self.core.get("register_parameter")("task", "bounds", self.control)
"Bounds", self.input_control, weight=30) self.core.register_ui("task_components", "Bounds",
self.control.get_widget(), weight=30)
self.core.register_event("bounds-list-changed", self._update_bounds) self.core.register_event("bounds-list-changed", self._update_bounds)
return True return True
def teardown(self): def teardown(self):
self.core.get("unregister_parameter")("task", "components", "bounds") self.core.get("unregister_parameter")("task", "bounds")
self.core.unregister_ui("task_models", self.control.get_widget())
self.core.unregister_event("bounds-list-changed", self._update_bounds) self.core.unregister_event("bounds-list-changed", self._update_bounds)
def _update_bounds(self): def _update_bounds(self):
...@@ -130,5 +137,5 @@ class TaskParamBounds(pycam.Plugins.PluginBase): ...@@ -130,5 +137,5 @@ class TaskParamBounds(pycam.Plugins.PluginBase):
bounds = self.core.get("bounds") bounds = self.core.get("bounds")
for bound in bounds: for bound in bounds:
choices.append((bounds.get_attr(bound, "name"), bound)) choices.append((bounds.get_attr(bound, "name"), bound))
self.input_control.update_choices(choices) self.control.update_choices(choices)
...@@ -74,14 +74,18 @@ class Tasks(pycam.Plugins.ListPluginBase): ...@@ -74,14 +74,18 @@ class Tasks(pycam.Plugins.ListPluginBase):
changed_set_event="task-type-changed", changed_set_event="task-type-changed",
changed_set_list_event="task-type-list-changed", changed_set_list_event="task-type-list-changed",
get_current_set_func=self._get_type) get_current_set_func=self._get_type)
self.models_parameter_widget = self.core.get( self.models_widget = pycam.Gui.ControlsGTK.ParameterSection()
"register_parameter_section")("task", "models") self.core.register_ui_section("task_models",
self.models_widget.add_widget,
self.models_widget.clear_widgets)
self.core.register_ui("task_parameters", "Collision models", self.core.register_ui("task_parameters", "Collision models",
self.models_parameter_widget, weight=20) self.models_widget.widget, weight=20)
self.components_parameter_widget = self.core.get( self.components_widget = pycam.Gui.ControlsGTK.ParameterSection()
"register_parameter_section")("task", "components") self.core.register_ui_section("task_components",
self.components_widget.add_widget,
self.components_widget.clear_widgets)
self.core.register_ui("task_parameters", "Components", self.core.register_ui("task_parameters", "Components",
self.components_parameter_widget, weight=10) self.components_widget.widget, weight=10)
# table # table
self._gtk_handlers.append((self.gui.get_object("TaskNameCell"), self._gtk_handlers.append((self.gui.get_object("TaskNameCell"),
"edited", self._edit_task_name)) "edited", self._edit_task_name))
...@@ -131,9 +135,10 @@ class Tasks(pycam.Plugins.ListPluginBase): ...@@ -131,9 +135,10 @@ class Tasks(pycam.Plugins.ListPluginBase):
if self.gui: if self.gui:
self.core.unregister_ui("main", self.gui.get_object("TaskBox")) self.core.unregister_ui("main", self.gui.get_object("TaskBox"))
self.core.unregister_ui("task_parameters", self.core.unregister_ui("task_parameters",
self.models_parameter_widget) self.models_widget)
self.core.unregister_ui("task_parameters", self.core.unregister_ui("task_parameters", self.components_widget)
self.components_parameter_widget) self.core.unregister_ui_section("task_models")
self.core.unregister_ui_section("task_components")
self.unregister_gtk_handlers(self._gtk_handlers) self.unregister_gtk_handlers(self._gtk_handlers)
self.unregister_event_handlers(self._event_handlers) self.unregister_event_handlers(self._event_handlers)
while len(self) > 0: while len(self) > 0:
......
...@@ -31,19 +31,21 @@ class ToolParamRadius(pycam.Plugins.PluginBase): ...@@ -31,19 +31,21 @@ class ToolParamRadius(pycam.Plugins.PluginBase):
CATEGORIES = ["Tool", "Parameter"] CATEGORIES = ["Tool", "Parameter"]
def setup(self): def setup(self):
control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=99, digits=0, self.control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=99,
change_handler=lambda widget=None: self.core.emit_event( digits=0, change_handler=lambda widget=None: \
"tool-changed")) self.core.emit_event("tool-changed"))
control.set_conversion(set_conv=lambda value: value * 2.0, self.control.set_conversion(set_conv=lambda value: value * 2.0,
get_conv=lambda value: value / 2.0) get_conv=lambda value: value / 2.0)
self.core.get("register_parameter")("tool", "size", "radius", self.core.get("register_parameter")("tool", "radius", self.control)
"Tool diameter", control, weight=10) self.core.register_ui("tool_size", "Tool Diameter",
self.control.get_widget(), weight=10)
self.core.register_chain("get_toolpath_information", self.core.register_chain("get_toolpath_information",
self.get_toolpath_information) self.get_toolpath_information)
return True return True
def teardown(self): def teardown(self):
self.core.get("unregister_parameter")("tool", "size", "radius") self.core.get("unregister_parameter")("tool", "radius")
self.core.unregister_ui("tool_size", self.control.get_widget())
self.core.unregister_chain("get_toolpath_information", self.core.unregister_chain("get_toolpath_information",
self.get_toolpath_information) self.get_toolpath_information)
...@@ -59,14 +61,17 @@ class ToolParamTorusRadius(pycam.Plugins.PluginBase): ...@@ -59,14 +61,17 @@ class ToolParamTorusRadius(pycam.Plugins.PluginBase):
CATEGORIES = ["Tool", "Parameter"] CATEGORIES = ["Tool", "Parameter"]
def setup(self): def setup(self):
control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=99, digits=0, self.control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=99,
change_handler=lambda widget=None: self.core.emit_event( digits=0, change_handler=lambda widget=None: \
"tool-changed")) self.core.emit_event( "tool-changed"))
self.core.get("register_parameter")("tool", "size", "torus_radius", self.core.get("register_parameter")("tool", "torus_radius",
"Torus radius", control, weight=20) self.control)
self.core.register_ui("tool_size", "Torus Radius",
self.control.get_widget(), weight=50)
return True return True
def teardown(self): def teardown(self):
self.core.unregister_ui("tool_size", self.control.get_widget())
self.core.get("unregister_parameter")("tool", "size", "torus_radius") self.core.get("unregister_parameter")("tool", "size", "torus_radius")
...@@ -76,16 +81,18 @@ class ToolParamFeedrate(pycam.Plugins.PluginBase): ...@@ -76,16 +81,18 @@ class ToolParamFeedrate(pycam.Plugins.PluginBase):
CATEGORIES = ["Tool", "Parameter"] CATEGORIES = ["Tool", "Parameter"]
def setup(self): def setup(self):
control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=10000, self.control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=10000,
digits=0, change_handler=lambda widget=None: \ digits=0, change_handler=lambda widget=None: \
self.core.emit_event("tool-changed")) self.core.emit_event("tool-changed"))
self.core.get("register_parameter")("tool", "speed", "feedrate", self.core.get("register_parameter")("tool", "feedrate", self.control)
"Feedrate", control, weight=10) self.core.register_ui("tool_speed", "Feedrate",
self.control.get_widget(), weight=10)
self.core.register_chain("get_toolpath_information", self.core.register_chain("get_toolpath_information",
self.get_toolpath_information) self.get_toolpath_information)
return True return True
def teardown(self): def teardown(self):
self.core.unregister_ui("tool_speed", self.control.get_widget())
self.core.get("unregister_parameter")("tool", "speed", "feedrate") self.core.get("unregister_parameter")("tool", "speed", "feedrate")
self.core.unregister_chain("get_toolpath_information", self.core.unregister_chain("get_toolpath_information",
self.get_toolpath_information) self.get_toolpath_information)
...@@ -101,16 +108,19 @@ class ToolParamSpindleSpeed(pycam.Plugins.PluginBase): ...@@ -101,16 +108,19 @@ class ToolParamSpindleSpeed(pycam.Plugins.PluginBase):
CATEGORIES = ["Tool", "Parameter"] CATEGORIES = ["Tool", "Parameter"]
def setup(self): def setup(self):
control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=100000, self.control = pycam.Gui.ControlsGTK.InputNumber(lower=0, upper=100000,
digits=0, change_handler=lambda widget=None: \ digits=0, change_handler=lambda widget=None: \
self.core.emit_event("tool-changed")) self.core.emit_event("tool-changed"))
self.core.get("register_parameter")("tool", "speed", "spindle_speed", self.core.get("register_parameter")("tool", "spindle_speed",
"Spindle speed", control, weight=20) self.control)
self.core.register_ui("tool_speed", "Spindle Speed",
self.control.get_widget(), weight=50)
self.core.register_chain("get_toolpath_information", self.core.register_chain("get_toolpath_information",
self.get_toolpath_information) self.get_toolpath_information)
return True return True
def teardown(self): def teardown(self):
self.core.unregister_ui("tool_speed", self.control.get_widget())
self.core.get("unregister_parameter")("tool", "speed", "spindle_speed") self.core.get("unregister_parameter")("tool", "speed", "spindle_speed")
self.core.unregister_chain("get_toolpath_information", self.core.unregister_chain("get_toolpath_information",
self.get_toolpath_information) self.get_toolpath_information)
......
...@@ -74,14 +74,16 @@ class Tools(pycam.Plugins.ListPluginBase): ...@@ -74,14 +74,16 @@ class Tools(pycam.Plugins.ListPluginBase):
changed_set_event="tool-shape-changed", changed_set_event="tool-shape-changed",
changed_set_list_event="tool-shape-list-changed", changed_set_list_event="tool-shape-list-changed",
get_current_set_func=self._get_shape) get_current_set_func=self._get_shape)
size_parameter_widget = self.core.get("register_parameter_section")( size_widget = pycam.Gui.ControlsGTK.ParameterSection()
"tool", "size")
self.core.register_ui("tool_parameters", "Size", self.core.register_ui("tool_parameters", "Size",
size_parameter_widget, weight=10) size_widget.widget, weight=10)
speed_parameter_widget = self.core.get("register_parameter_section")( self.core.register_ui_section("tool_size",
"tool", "speed") size_widget.add_widget, size_widget.clear_widgets)
speed_widget = pycam.Gui.ControlsGTK.ParameterSection()
self.core.register_ui("tool_parameters", "Speed", self.core.register_ui("tool_parameters", "Speed",
speed_parameter_widget, weight=20) speed_widget.widget, weight=20)
self.core.register_ui_section("tool_speed",
speed_widget.add_widget, speed_widget.clear_widgets)
# table updates # table updates
cell = self.gui.get_object("ToolTableShapeCell") cell = self.gui.get_object("ToolTableShapeCell")
self.gui.get_object("ToolTableShapeColumn").set_cell_data_func( self.gui.get_object("ToolTableShapeColumn").set_cell_data_func(
......
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