Advanced dialogs¶

Advanced dialogs¶
  1import win32com.client
  2import win32com.server.util
  3
  4
  5class _CallbackSink:
  6    # COM adapter: Impact invokes dialog callbacks via IDispatch dispid 0
  7    _public_methods_ = ["Invoke0"]
  8    _dispid_to_func_ = {0: "Invoke0"}
  9
 10    def Invoke0(self, raw_params):
 11        try:
 12            return callback(IDialogCallbackParams(win32com.client.Dispatch(raw_params)))
 13        except Exception as exc:
 14            # ShowModal ignores callback errors; report them or they vanish silently
 15            impact.gui.output_toolbox.add(f"Callback error: {exc!r}")
 16
 17
 18preview_file1 = r"d:\preview1.ipd"
 19preview_file2 = r"d:\preview2.ipd"
 20
 21picture_file1 = r"d:\picture1.jpg"
 22picture_file2 = r"d:\picture2.jpg"
 23
 24
 25# Define a function to describe a constant from the ipDialogCallbackReason enumeration
 26_DESCRIBE_CALLBACK_REASON_MAP = {
 27    ipDialogCallbackReason.dcrFieldSelected: "Field Selected",
 28    ipDialogCallbackReason.dcrFieldCurrent: "Field Current",
 29    ipDialogCallbackReason.dcrFieldNonCurrent: "Field Non Current",
 30    ipDialogCallbackReason.dcrDialogClosing: "DialogClosing",
 31}
 32
 33def describe_callback_reason(reason):
 34    return _DESCRIBE_CALLBACK_REASON_MAP.get(reason, "Unknown")
 35
 36# Define a function to describe a constant from the ipDialogButtonType enumeration
 37_DESCRIBE_DIALOG_BUTTON_TYPE_MAP = {
 38    ipDialogButtonType.dbtUnknown: "Unknown",
 39    ipDialogButtonType.dbtOk: "Ok",
 40    ipDialogButtonType.dbtCancel: "Cancel",
 41    ipDialogButtonType.dbtYes: "Yes",
 42    ipDialogButtonType.dbtNo: "No",
 43    ipDialogButtonType.dbtNext: "Next",
 44    ipDialogButtonType.dbtPrevious: "Previous",
 45    ipDialogButtonType.dbtClose: "Close",
 46    ipDialogButtonType.dbtPrint: "Print",
 47    ipDialogButtonType.dbtCustom: "Custom",
 48}
 49
 50def describe_dialog_button_type(button_type):
 51    return _DESCRIBE_DIALOG_BUTTON_TYPE_MAP.get(button_type, "Unknown")
 52
 53# Define a function to describe a constant from the ipDialogFieldType enumeration
 54_DESCRIBE_DIALOG_FIELD_TYPE_MAP = {
 55    ipDialogFieldType.dftUnknown: "Unknown",
 56    ipDialogFieldType.dftAngle: "Angle",
 57    ipDialogFieldType.dftArea: "Area",
 58    ipDialogFieldType.dftCheckBox: "Check Box",
 59    ipDialogFieldType.dftComboBox: "Combo Box",
 60    ipDialogFieldType.dftDate: "Date",
 61    ipDialogFieldType.dftDistance: "Distance",
 62    ipDialogFieldType.dftInteger: "Integer",
 63    ipDialogFieldType.dftLine: "Line",
 64    ipDialogFieldType.dftListBox: "List Box",
 65    ipDialogFieldType.dftPreview: "Preview",
 66    ipDialogFieldType.dftRadioGroup: "Radio Group",
 67    ipDialogFieldType.dftReal: "Real",
 68    ipDialogFieldType.dftText: "Text",
 69    ipDialogFieldType.dftTextBox: "Text Box",
 70    ipDialogFieldType.dftTime: "Time",
 71    ipDialogFieldType.dftTwinList: "Twin List",
 72    ipDialogFieldType.dftVolume: "Volume",
 73    ipDialogFieldType.dftWeight: "Weight",
 74    ipDialogFieldType.dftPicture: "Picture",
 75    ipDialogFieldType.dftButton: "Button",
 76}
 77
 78def describe_dialog_field_type(field_type):
 79    return _DESCRIBE_DIALOG_FIELD_TYPE_MAP.get(field_type, "Unknown")
 80
 81# Define a sub routine to display a list of items in the output toolbox
 82def display_list_values(message, list):
 83    ot.add(message)
 84
 85    for item in list:
 86        ot.add(item)
 87
 88# Define a callback(), passed into the ShowModal method of IDialog
 89def callback(callback_params):
 90    field = callback_params.field
 91
 92    if not field.isNone():
 93        ot.add(field.label + ": " + str(describe_callback_reason(callback_params.reason)))
 94
 95        if field.field_type == ipDialogFieldType.dftPicture:
 96            ot.add("HasImage: " + str(field.picture_has_image))
 97        else:
 98            ot.add("Value: " + str(field.value))
 99
100        if field.label == "Click Me!":
101            impact.gui.show_message(ipShowMessageType.smtInfo, "You clicked me!", None)
102
103        elif field.label == "Preview Group":
104            if field.value == 0:
105                preview_field.show_preview(preview_file1, "One up", True)
106            else:
107                preview_field.show_preview(preview_file2, "One up", True)
108
109        elif field.label == "load Picture 1":
110            pic1_field.show_picture(picture_file1)
111
112        elif field.label == "load Picture 2":
113            pic1_field.show_picture(picture_file2)
114
115        elif field.field_type == ipDialogFieldType.dftPicture:
116            if pic1_field.picture_has_image:
117                if pic1_field.picture_file_name == "":
118                    impact.gui.show_message(ipShowMessageType.smtInfo, "The image was changed from the clipboard", None)
119
120                else:
121                    impact.gui.show_message(ipShowMessageType.smtInfo, "The image was changed and loaded from '" + str(pic1_field.picture_file_name) + "'", None)
122
123            else:
124                impact.gui.show_message(ipShowMessageType.smtInfo, "The image was cleared", None)
125
126
127    if callback_params.reason == ipDialogCallbackReason.dcrDialogClosing:
128        ot.add(describe_dialog_button_type(callback_params.button_type))
129
130        if callback_params.button_type == ipDialogButtonType.dbtOk:
131            callback_params.can_close = allow_close_field.value
132
133
134# Create a local variable for the impact impact.gui object
135g = impact.gui
136
137# Create a local variable for the output toolbox
138ot = g.output_toolbox
139
140# Create a dialog
141d = g.make_dialog("Options")
142
143# Check the dialog was created
144if not d.isNone():
145
146    # Create a local variable for the fields of the dialog
147    fields = d.fields
148
149    # Build up the controls to display in the dialog
150    d.add_button(ipDialogButtonType.dbtOk)
151
152    types_tab = d.add_tab("Types")
153
154    fields.add_line("Simple Types")
155
156    check_box_field = fields.add_check_box(False, "Boolean")
157    check_box_field.value = True
158    check_box_field.use_callback = True
159
160    integer_field = fields.add_integer(5, "Integer")
161    integer_field.value = 2
162    integer_field.use_callback = True
163
164    real_field = fields.add_real(91.2, "Real")
165    real_field.value = 6.23
166    real_field.use_callback = True
167
168    text_field = fields.add_text("Simple text", "Text")
169    text_field.value = "Modified simple text"
170    text_field.case = ipDialogStringCase.dscAll
171    text_field.chars = ipDialogStringChars.dshAll
172
173    short_text_field = fields.add_text("AA123", "Short text")
174    short_text_field.max_length = 5
175    short_text_field.case = ipDialogStringCase.dscUpper
176    short_text_field.chars = ipDialogStringChars.dshAlphaNumeric
177    short_text_field.use_callback = True
178
179    text_box_field = fields.add_text_box("Advanced text" + "\r\n" + "New Line", "Text Box")
180    text_box_field.value = "Modified advanced text" + "\r\n" + "New Line"
181    text_box_field.use_callback = True
182
183    date_field = fields.add_date(datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0), "Date")
184    date_field.value = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
185    date_field.use_callback = True
186
187    time_field = fields.add_time(datetime.datetime.now(), "Time")
188    time_field.value = datetime.datetime.now()
189    time_field.use_callback = True
190
191    fields.add_line("Advanced Types")
192
193    distance_field = fields.add_distance(-200.0, "Distance", True)
194    distance_field.value = 100.0
195    distance_field.hint = "Enter a distance"
196    distance_field.use_callback = True
197
198    angle_field = fields.add_angle(45.0, "Angle" + "\r\n" + "(use 90 if possible)")
199    angle_field.value = 180.0
200    angle_field.use_callback = True
201
202    weight_field = fields.add_weight(9.2, "Weight")
203    weight_field.value = 64.5
204    weight_field.use_callback = True
205
206    area_field = fields.add_area(8.6, "Area")
207    area_field.value = 23.9
208    area_field.use_callback = True
209
210    volume_field = fields.add_volume(2.4, "Volume")
211    volume_field.value = 15.2
212    volume_field.use_callback = True
213
214    button_field = fields.add_button("Click Me!")
215
216    button_field.hint = "Click this button to show how a callback() is triggered"
217
218    # Adds a checkbox field to control the closing of the dialog
219    allow_close_field = fields.add_check_box(False, "Allow close on OK")
220    allow_close_field.value = True
221    allow_close_field.use_callback = True
222
223    lists_tab = d.add_tab("Lists")
224
225    fruits = ["Orange", "Apple", "Banana", "Lemon", "Pineapple", "Kiwi", "Strawberry", "Lime"]
226
227    fields.add_line("Select a single fruit from this list")
228
229    combo_box_field = fields.add_combo_box("Lemon", "Fruit Combo", fruits)
230
231    # Set combo_box_field = fields.add_combo_box(3, "Fruit Combo", fruits, False)
232    # combo_box_field.value = 4
233    combo_box_field.value = "Kiwi"
234    combo_box_field.use_callback = True
235
236    selection = [False, True, False, True, False, True, False, True]
237
238    fields.add_line("Select none or more fruits from this list box")
239
240    list_box_field = fields.add_list_box(fruits, selection, True, 5)
241    list_box_field.height = 5
242
243    fields.add_line("Select a single fruit from this group")
244
245    radio_group_field = fields.add_radio_group("Apple", "Fruit Group", fruits)
246
247    # Set radio_group_field = fields.add_radio_group(1, "Fruit Group", fruits)
248    # radio_group_field.value = 2
249    radio_group_field.value = "Banana"
250    radio_group_field.use_callback = True
251
252    fields.add_line("Select none or more fruits from this twin list")
253
254    twin_list_field = fields.add_twin_list("Left", "Right", fruits, selection, 6)
255    twin_list_field.height = 6
256
257    preview_tab = d.add_tab("Preview")
258
259    previews = ["Preview 1", "Preview 2"]
260
261    preview_group_field = fields.add_radio_group("Preview 1", "Preview Group", previews)
262    preview_group_field.use_callback = True
263
264    preview_field = fields.add_preview(preview_file1, "One up", True, ipDialogPreviewOrientation.dpoVertical)
265
266    picture_tab = d.add_tab("Picture")
267
268    pic1_opts = impact.gui.create_dialog_picture_options()
269
270    pic1_opts.width = 320
271    pic1_opts.height = 240
272
273    pic1_opts.command_panel_position = ipDialogPictureCommandsPosition.dpcpRightTop
274    pic1_opts.command_panel_always_visible = True
275
276    pic1_field = fields.add_picture(picture_file1, "Picture1", pic1_opts)
277
278    pic1_field.use_callback = True
279
280    load_pic1_button = fields.add_button("load Picture 1")
281    load_pic2_button = fields.add_button("load Picture 2")
282
283    # Display the type of each field in the output toolbox
284    for field in fields:
285        ot.add(describe_dialog_field_type(field.field_type))
286
287    # Show the dialog with a callback() handler
288    button_pressed = d.show_modal(win32com.server.util.wrap(_CallbackSink()))
289
290    if button_pressed == ipDialogButtonType.dbtOk:
291
292        # Display the values from the dialog
293        ot.add(check_box_field.label + ": " + str(check_box_field.value))
294        ot.add(integer_field.label + ": " + str(integer_field.value))
295        ot.add(real_field.label + ": " + str(real_field.value))
296        ot.add(text_field.label + ": " + str(text_field.value))
297        ot.add(text_box_field.label + ": " + str(text_box_field.value))
298        ot.add(date_field.label + ": " + str(date_field.value))
299        ot.add(time_field.label + ": " + str(time_field.value))
300
301        ot.add(distance_field.label + ": " + str(distance_field.value))
302        ot.add(angle_field.label + ": " + str(angle_field.value))
303        ot.add(weight_field.label + ": " + str(weight_field.value))
304        ot.add(area_field.label + ": " + str(area_field.value))
305        ot.add(volume_field.label + ": " + str(volume_field.value))
306
307        ot.add(radio_group_field.label + ": " + str(radio_group_field.value))
308        ot.add(radio_group_field.label + ": " + str(radio_group_field.selected_item))
309
310        ot.add(combo_box_field.label + ": " + str(combo_box_field.value))
311        ot.add(combo_box_field.label + ": " + str(combo_box_field.selected_item))
312
313        display_list_values("Listbox selected values:", list_box_field.selected_items)
314        display_list_values("Listbox selected indicies:", list_box_field.selected_indices)
315        display_list_values("Twinlist selected values:", twin_list_field.selected_items)
316        display_list_values("Twinlist selected indicies:", twin_list_field.selected_indices)
317
318        ot.add(pic1_field.label + ": " + str(pic1_field.picture_file_name))