Announcement: MiniWord

Just checked and didn’t have problems on linux and windows. MarkDown can be loaded using “open” and “import” or by dropping a file on the mainwindow.

The error message indicates that the md-plugin was not loaded, which is strange since it is directly built in now. You can check it in the “open” dialog: if “*.md” is offered as a file filter, then it is ok. Maybe try to remove AppData\Roaming\miniword.

Plugins are loaded in miniword\ui\mainwindow.py in function load_plugins.

Sorry, the latest commits were missing. Now it’s working.
An outline / navigation view would be nice.

I placed the libcairo dll in the application directory.
For this I need to use abspath as location is just `libcairo-2.dll’:
cairoLib = ctypes.CDLL(os.path.abspath(location))

OK, we have an outline view now. I think it is quite nice, so thanks for the idea.

By the way: to my surprise I found that the libcairo-dll is already included in the Windows-version of wxpython. So, it is not necessary to manually install it.

Hello Chris,
Thank you for this excellent open source tool which enriches the wxpython framework.

Here is what I noticed when testing your application on Windows:

  • A recurring problem when downloading your project’s source files from the “Codeberg.org” site:

  • After starting the “test_all.py” file, the result shows 3 failed:

======================== RESTART: C:\Users\Me\Downloads\miniword-main\miniword\test_all.py =======================
################ miniword.textmodel.texeltree ################

test_00: insert… ok
test_01: growth in insert… ok
test_02: maintaining tree efficency in insert / takeout… ok
test_03: depth… ok
test_04: fuse… ok
test_06: insert in container… ok
test_07: compute_hull… ok
test_08: takeout… ok
test_09: pickle… ok
test_10: set_style… ok
test_11: set_parstyle… ok
test_12: transform… ok
Number of tests: 12
Tests failed: 0
################ miniword.textmodel.iterators ################
test_00: iter_leafes… ok
Number of tests: 1
Tests failed: 0
################# miniword.textmodel.styles #################
test_00: get_style… ok
test_01: get_styles… ok
test_10: set_styles… ok
test_11: set_properties… ok
test_12: set_parstyles… ok
Number of tests: 5
Tests failed: 0
################# miniword.textmodel.weights #################
test_00: find_newline… ok
test_01: find_weight… ok
test_02: get_weight… ok
Number of tests: 3
Tests failed: 0
################ miniword.textmodel.textmodel ################
test_00: remove w. simplify… ok
test_01: row, col… ok
test_03: TextModel… ok
test_04: indices… ok
test_05: style… ok
test_06: get_style… ok
test_08: insert/remove… ok
test_09: slice… ok
test_10: split… ok
test_11: properties… ok
test_12: remove all… ok
test_13: ENDMARK… ok
test_14: random insert/remove… ok
test_15: get/set styles… ok
test_16: undo properties… ok
test_17: Tabulator… ok
test_18: dump_range… ok
test_19: get/set parstyle… ok
test_20: indent… ok
test_21: expand_range… ok
test_22: get_start / get_end… ok
test_23: get_parstyle inside a container… ok
Number of tests: 22
Tests failed: 0
################ miniword.wxtextview.linewrap ################
test_00: find_break… ok
test_01: simple_linewrap… ok
Number of tests: 2
Tests failed: 0
############### miniword.wxtextview.markbuffer ###############
test_00: add_mark… ok
test_01: remove_mark… ok
test_02: insert… ok
test_03: remove… ok
test_04: get_marks… ok
Number of tests: 5
Tests failed: 0
############## miniword.wxtextview.simplelayout ##############
test_00: Paragraph… ok
test_01: Row… ok
test_02: get_envelope… ok
test_02a: create_paragraphs… ok
test_03: … ok
test_04: … ok
test_05: … ok
Number of tests: 7
Tests failed: 0
################# miniword.wxtextview.boxes #################
test_00: TextBox… ok
test_01: HBox… ok
test_02: VBox… ok
test_03: grouped… ok
test_04: replace_boxes… ok
test_05: get_cursorrect… ok
test_06: get_index… ok
test_07: find_text_pos… ok
Number of tests: 8
Tests failed: 0
################ miniword.wxtextview.builder ################
test_01: … ok
Number of tests: 1
Tests failed: 0
############### miniword.wxtextview.wxtextview ###############
test_02: setting cursor & selection… ok
test_03: inserting text… ok
test_04: insert/remove… ok
test_05: remove… ok
test_09: linebreak… ok
test_10: linebreak after insert… ok
test_11: relayout after changes… ok
test_13: exception during delete 10.01.2015… ok
test_14: join_undo… ok
Number of tests: 9
Tests failed: 0
################## miniword.core.stylesheet ##################
test_00: … ok
Number of tests: 1
Tests failed: 0
#################### miniword.core.styles ####################
test_00: … ok
test_01: … ok
Number of tests: 2
Tests failed: 0
################### miniword.core.document ###################
test_00: receiving child messages via fallback handler… ok
test_01: forwarding basestyles changes to views… ok
Number of tests: 2
Tests failed: 0
#################### miniword.core.utils ####################
test_00: selection not touching any separator is unchanged ok
test_01: selection spanning a separator expands to full container ok
test_02: selection touching left separator expands to full container ok
test_03: nested container: inner separator expands to full inner container ok
test_04: nested container: selection touching outer separator expands to full outer ok
test_05: get_path… ok
test_06: get_texel… ok
test_07: find_texel… ok
test_08: transform… ok
Number of tests: 9
Tests failed: 0
################ miniword.layout.stretchable ################
test_00: … ok
test_01: find_x… ok
test_02: set_stretch… ok
test_03: justify_line… ok
Number of tests: 4
Tests failed: 0
################# miniword.layout.annotation #################
test_00: highlight… ok
test_01: iter_textboxes… ok
Number of tests: 2
Tests failed: 0
################ miniword.layout.cairodevice ################
test_00: … error
File “C:\Users\Me\Downloads\miniword-main(1)\miniword\miniword\layout\cairodevice.py”, line 402, in test_00
assert metrics == (8.330078125, 11.4990234375, 2.119140625)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
test_01: … error
File “C:\Users\Me\Downloads\miniword-main(1)\miniword\miniword\layout\cairodevice.py”, line 411, in test_01
gc = wx.GraphicsContext.Create(dc)
wx._core.wxAssertionError: C++ assertion “bmp.IsOk()” failed at …..\src\msw\graphics.cpp(2708) in wxGDIPlusRenderer::CreateContext(): Should select a bitmap before creating wxGCDC
test_02: Computing text extent… error
File “C:\Users\Me\Downloads\miniword-main(1)\miniword\miniword\layout\cairodevice.py”, line 452, in test_02
gc = wx.GraphicsContext.Create(dc)
wx._core.wxAssertionError: C++ assertion “bmp.IsOk()” failed at …..\src\msw\graphics.cpp(2708) in wxGDIPlusRenderer::CreateContext(): Should select a bitmap before creating wxGCDC
Number of tests: 3
Tests failed: 3
################## miniword.layout.builder ##################
test_01: generate_pages… ok
test_02: restartmemo… ok
Number of tests: 2
Tests failed: 0
################## miniword.layout.pagegen ##################
test_00: … ok
test_01: start and fix draft… ok
test_02: generate_pages… ok
Number of tests: 3
Tests failed: 0
################ miniword.io.texeltreeformat ################
test_00: Roundtrip: Text with style… ok
test_01: Roundtrip: NewLine with parStyle and indent… ok
test_02: Roundtrip: Container (Fraction)… ok
test_03: Roundtrip: Nested containers… ok
test_04: Roundtrip: Container slot with style… ok
test_05: Roundtrip: document properties… ok
test_06: Roundtrip: Container with ncols… ok
test_07: Roundtrip: BR (forced line break)… ok
test_08: Roundtrip: Table with cell attrs and nheader… ok
Number of tests: 9
Tests failed: 0
##################### miniword.io.txlio #####################
test_00: roundtrip… ok
test_01: basestyles roundtrip… ok
test_02: missing sections… ok
test_03: load einstein.txl… ok
test_04: blobs roundtrip… ok
Number of tests: 5
Tests failed: 0
################## miniword.io.importexport ##################
test_00: roundtrip plain text… ok
test_01: find_filter by extension… ok
test_02: wildcard contains Plain Text… ok
test_03: open_wildcard includes TXL… ok
test_04: check_export plain text warns about formatting… ok
test_05: check_export unknown format returns empty list… ok
Number of tests: 6
Tests failed: 0
################### miniword.tables.tables ###################
test_00: from_strings… ok
test_01: get_cells, from_cells… ok
test_02: set_cellattr… ok
test_03: insert_cols… ok
test_04: get_coord… ok
test_05: remove_rows… ok
test_06: remove_cols… ok
test_07: insert_rows… ok
test_08: get_rect… ok
test_09: get_cell_ranges… ok
test_10: set cell alignment… ok
test_11: col_widths preserved by set_cellattr, insert_rows, remove_rows ok
test_12: col_widths adjusted by insert_cols, remove_cols… ok
Number of tests: 13
Tests failed: 0
################ miniword.tables.table_boxes ################
test_07: navigation: TableNavRow.get_index selects the cell matching x at y=row_height ok
test_08: navigation: for a multi-line cell, get_index at y=height lands in the last row ok
test_09: navigation: Up from top of row r lands at bottom of multi-line cells in row r-1 ok
test_11: split_table_box divides rows, preserves total length, links prev/next ok
Number of tests: 4
Tests failed: 0
############### miniword.tables.table_factory ###############
test_03: build_table_box produces TableBox with correct length ok
Number of tests: 1
Tests failed: 0
############### miniword.tables.table_editors ###############
test_00: _draw_frag_selection calls invert_rect once per selected cell ok
test_04: MatrixEditor.copy… ok
test_05: MatrixEditor.selected returns absolute positions. ok
Number of tests: 3
Tests failed: 0
################### miniword.images.images ###################
test_00: Image texel: defaults… ok
test_01: Image texel: scale_x, scale_y and crop… ok
test_02: ImageBox fallback: None bitmap… ok
test_03: ImageBox: length and geometry… ok
Number of tests: 4
Tests failed: 0
################### miniword.ui.stylemenu ###################
test_00: mk_label… ok
test_01: BasestyleSelector – modified flag… ok
test_02: CreateNewStyle… ok
test_03: UpdateStyle… ok
test_04: DeleteStyle – blocks ‘normal’, fires callback for other styles ok
Number of tests: 5
Tests failed: 0
################# miniword.ui.styleinspector #################
test_00: get_parstyle… ok
Number of tests: 1
Tests failed: 0
################### miniword.ui.searchtool ###################
test_00: … ok
test_01: case sensitivity… ok
test_02: regex and whole word… ok
test_03: replace via model operations… ok
Number of tests: 4
Tests failed: 0
################## miniword.ui.documentview ##################
test_00: modifying a basestyle updates the layout… ok
test_accumulate: accumulate: combining two update ranges… ok
Number of tests: 2
Tests failed: 0
################# miniword.plugins.mdfilter #################
test_00: normal paragraph… ok
test_01: headings h1–h3… ok
test_02: heading with continuation line (blank line before next) ok
test_03: bold and italic… ok
test_03b: single-character italic and bold… ok
test_04: bold+italic combined… ok
test_05: inline code… ok
test_06: unordered list — top-level items have indent 0… ok
test_07: ordered list — top-level items have indent 0… ok
test_08: nested list — deeper indent… ok
test_09: list item with continuation line… ok
test_10: fenced code block uses pre basestyle… ok
test_11: export roundtrip: headings, lists and code block. ok
test_12: table import produces Table texel with correct dimensions and cell texts ok
test_13: table export roundtrip preserves headers and data rows ok
test_14: blank NL paragraphs are inserted before and after table and pre blocks ok
test_15: blockquote import and export roundtrip… ok
test_16: blank NL paragraphs are inserted before and after quote blocks ok
Number of tests: 18
Tests failed: 0

==============================================================
Total: 178 tests, 3 failed

  • When exiting the application, a new error appears:

Traceback (most recent call last):
File “C:\Users\Me\Downloads\miniword-main(1)\miniword-main\miniword\miniword\ui\sidepanel.py”, line 127, in on_show
self.update_visible()
~~~~~~~~~~~~~~~~~~~^^
File “C:\Users\Me\Downloads\miniword-main(1)\miniword-main\miniword\miniword\ui\sidepanel.py”, line 140, in update_visible
self.visible = self.IsShownOnScreen()
~~~~~~~~~~~~~~~~~~~~^^
RuntimeError: wrapped C/C++ object of type StyleInspector has been deleted

  • When I enter text on the screen, characters appear to the right of the cursor as new words are added (see video below):

video.zip (54.2 KB)

  • Wrong characters are displayed in the “README.md” file (v3.0 – €):

License

This project is licensed under the GNU General Public License v3.0 – see LICENSE for details. Contact me if you need something else.

#--------------------

I also have a small suggestion, could you add an option to display two pages side by side?

#--------------------

Configuration used for the test:

  • Windows 11
  • Python 3.13.7
  • wxPython 4.2.5
  • wxWidget 3.2.9

Regards

Hello, thanks for the detailed feedback! This is very helpful.

  • Codeberg: Yes, they sometimes have hiccups, unfortunately out of my control.
  • RuntimeError: Thanks! I’ve fixed the sidepanel.py issue where the object was accessed after being deleted.
  • Test Assertions: The cairodevice errors are due to platform-specific font rendering and a missing bitmap initialization on Windows. I will update the tests to be more robust.
  • bmp.IsOK():* Fixed it.
  • Typing/Cursor Issue: I watched the video. I will investigate this.
  • Two-page view: Good suggestion! I’ll put it on the roadmap.

Regards, Chris

I made an experimental branch (‘harfbuzz’) with better font substitution and initial support for Asian line breaking.

HarfBuzz handles complex script shaping much better, which should solve the ‘missing commas’ in Armenian by correctly falling back to compatible fonts. For CJK (Chinese, Japanese, Korean), the branch also includes logic to allow breaks between characters even without spaces.

The solution also gives us ligatures and kerning. The downside is that this adds more dependencies (uharfbuzz and fonttools), so I am not 100% sure if I should merge this into the main branch.

Below are the latest anomalies encountered:

  • Styles (bold, underline, italic) modify the baseline of the selected characters:

  • The “Outline” tool displays nothing:

Thanks,
the empty outline can be explained. In miniword basestyles have roles. The role is what make a heading behave as a heading. The einstein text predates this concept. “Heading 1” is not seen in the outline, since the role is not assigned (which can be done in the styles panel under other->semantics). I made the assignment for the other demos, look at moby.txl or tesla.txl.

The baselines look perfect under linux, on window there is something strange. I assume it is a font problem since miniword uses the platform fonts, which do differ. I will look into that, thanks.

Not sure if it is the right time to request such a minor feature, but could you make the “unsaved changes” dialog configurable? Because different editors ask different questions in different ways: “Unsaved changes, save them first? (Yes/No)” “Unsaved changes, quit anyway? (Yes/No)” Or sometimes it’s (No/Yes), like in your case. Or (Yes/No/Cancel). Or (Save/Don’t save/Cancel). Or whatever. Would be nice to be able to set it the way it is, say, in your most used source code editor, so you could just rely on your muscle memory. I think it should be rather easy to even make it “skinnable” with a user-modifiable XRC file.

Fixed it. Should work now. It is a strange effect though.

[quote=“Yoklmn, post:29, topic:40439, full:true”]
Not sure if it is the right time to request such a minor feature, but could you make the “unsaved changes” dialog configurable?

I changed it to the “discard, cancel, save” - variant. I think it is more common and expected by most users.

Hello Christof,
Here are the last two minor errors detected*:

- Menu “View —> Actual size”:

Traceback (most recent call last):
File “C:\Users\Me\Desktop\MiniWord\miniword\miniword\ui\mainwindow.py”, line 317, in
self.Bind(wx.EVT_MENU, lambda _: self.textview.set_zoom(self.textview._default_zoom), id=wx.ID_ZOOM_100)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: ‘DocumentView’ object has no attribute ‘_default_zoom’

- Menu “File —> Reload”:

Traceback (most recent call last):
File “C:\Users\Me\Desktop\MiniWord\miniword\miniword\ui\mainwindow.py”, line 730, in _on_reload
self.replace_document(doc)
~~~~~~~~~~~~~~~~~~~~~^^^^^
File “C:\Users\Me\Desktop\MiniWord\miniword\miniword\ui\mainwindow.py”, line 775, in replace_document
self._outline_panel.set_document(doc)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: ‘OutlinePanel’ object has no attribute ‘set_document’

#-------------------------

SUGGESTION

The keyboard shortcuts “Zoom In —> Ctrl++” and “Zoom Out —> Ctrl±” should also be available with the numeric keypad.

When a stable version is available, could you create a new page on the forum in the “wxPython Dev” category? I plan to create a page on the wxPython wiki with a link to your layout tool.

I sincerely hope that your application will be updated and maintained over time because it’s really worth it.

Many thanks for this fantastic work and your quick response.

Regards

** and for information, I confirm that your latest patch fixed the baseline on Windows.

ChrisEcker,

Thanks for this – it looks very interesting, and a very good start. It seems very intuitive to use. I would be interested in trying to use this in some of my applications as a “reporting and logging” tool, especially in the sense of embeddable WYSISYW Markdown editor. But I have a couple of comments, suggestions, requests. FWIW, I only tested on macOS with Python 3.13.10, wxPython 4.2.4.

Images: I can add an image from a file, and even resize it - Great! It would be nice to be able to move and/or export an imge. If I save to MD, the images is omitted, without warning. If I save to PDF, the image is included. If I save to “TXL”, the image included, but the TXL file format is something I don’t recognize. Is this a standard?

Tables: I can insert a table, but doing so seems a bit flaky. Selecting with the Grid seems to not insert, but using “insert custom table” does work reliably. It would be great if this supported something like “headings”. Tables are saved in MD files, but maybe not correctly.

Document Location: When opening an image to insert, it seems the application moves the “working directory” to that folder, so that a “Save” will now default to the image folder, instead of the folder the document had been in. I think this should be fixed. Alseo, export to PDF does not impose or even default to a suffix of “.pdf”. I think that will confuse many people.

General: For editing MD, it would be nice to be able to toggle to “Plain Text with MD formatting”.

Source Location: Using Codeberg is certainly an understandable choice. Not using GitHub will add a burden for potential collaborators. With a project this ambitious, you probably will want help.

License: the license used for any code is certainly the prerogative of the authors. If you are thinking of this project solely as an end-user application, that license may not matter. Using GPL for a Python project may limit the number of collaborators. It will impact whether it can be used as a library. I will say that I would not be able to include a GPL-ed miniword in my projects.

Thanks.

Thanks for the positive feedback — much appreciated! The comments are very helpful too. Please let me know if you succeed with the library integration or if you have questions about the source code.

  • Move images: We don’t have floating images yet. Images are inline elements, like text. You can simply move by cut/copy/paste.
  • Export images: I added a button for that.
  • TXL format: TXL is a simple text-based file format of my own design. It is simple enough to edit manually, and diffs are meaningful. Just open one of the example files to get a feel for it.
  • Working directory problem: Fixed.
  • PDF suffix problem: Fixed.
  • Plain text MD-view: I have an idea how to implement this, but it would be quite challenging. I’ll postpone it for now but keep it on the list.
  • Flaky table insert: This shouldn’t happen — on Linux and Windows it works reliably. Could you describe more precisely what is happening? You can run the table panel standalone with:
    python runtests.py miniword/tables/table_panel.py demo_00
    Are there any error messages in the terminal?
  • GitHub vs. Codeberg: I am considering moving back to GitHub.
  • License: Changed to LGPL.

The typing problem probably occured because key-events arrrived faster than they could be processed. Now this situation is handled correctly.

ChrisEcker,

Thanks very much for both the quick reply and encouraging responses.

For Table Insert (including your dem_00), what I see on macOS is that when using the 10x8 grid to set the table layout, the “Button Release” event does not work to insert the table, as it does on Linux (and I assume Windows). I’ll try to produce a better Issue.

It’s me again!

● Enter the text, apply a left indentation level, and then press the “Enter” or “Return” key.

video.zip (533.4 KB)

Traceback (most recent call last):
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\wxtextview\wxtextview.py”, line 142, in on_char
self.handle_action(action, shift)
~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\ui\documentview.py”, line 185, in handle_action
return WXTextView.handle_action(self, action, shift)
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\wxtextview\textview.py”, line 568, in handle_action
if handler(self, action, shift, ctx):
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\wxtextview\textview.py”, line 965, in default_handler
view.insert_newline(index, style, parstyle)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\wxtextview\textview.py”, line 523, in insert_newline
self.insert(index, tmp)
~~~~~~~~~~~^^^^^^^^^^^^
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\wxtextview\textview.py”, line 333, in insert
self.add_undo(info)
~~~~~~~~~~~~~^^^^^^
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\wxtextview\textview.py”, line 281, in add_undo
joined = self.join_undo(info, self._undoinfo[0])
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\wxtextview\textview.py”, line 247, in join_undo
if info1[0] == info2[0]:
~~~~~^^^
IndexError: list index out of range

################################

● The “Insert image…” button remains grayed out after adding an image. The button does not refresh.
It returns to its normal state when I hover over it.

################################

● The following may not be important:

test_all.py :

Warning: uharfbuzz not found — complex-script shaping and font fallback disabled. Install with: pip install uharfbuzz
################ miniword.layout.cairodevice ################

test_00: … error
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\layout\cairodevice.py”, line 544, in test_00
assert metrics == (8.328125, 11.4990234375, 2.119140625)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
test_01: … error
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\layout\cairodevice.py”, line 577, in test_01
assert eq(w, 163)
~~^^^^^^^^
AssertionError
test_02: Computing text extent… error
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\layout\cairodevice.py”, line 609, in test_02
assert width == 540
^^^^^^^^^^^^
AssertionError
Number of tests: 3
Tests failed: 3

After installing uharfbuzz :

################ miniword.layout.cairodevice ################

test_00: … error
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\layout\cairodevice.py”, line 544, in test_00
assert metrics == (8.328125, 11.4990234375, 2.119140625)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
test_01: … error
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\layout\cairodevice.py”, line 577, in test_01
assert eq(w, 163)
~~^^^^^^^^
AssertionError
test_02: Computing text extent… error
File “C:\Users\Me\Desktop\MiniWord\miniword-main\miniword\miniword\layout\cairodevice.py”, line 609, in test_02
assert width == 540
^^^^^^^^^^^^
AssertionError
Number of tests: 3
Tests failed: 3

################################

● Asian languages appear to function correctly and i confirm that the typing problem has been resolved.


Regards

Thanks! The undo-exception is a bug is is fixed now. The greyed out button is a follow up problem and also should be solved now. The width assertions should be removed, since we have different metrics now, depending on platform and availability of harfbuzz.

“”"
The grayed out button is a follow up problem and also should be solved now.
“”"
No, the problem still persists on Windows.
video.zip (312.7 KB)

However, if you apply a “self.Refresh()” in the “image_panel” file (using the _on_insert & _on_export functions) and change the button’s state from “hover” to “normal” (using the flatbutton / on_release file), the problem is solved for me.


I replaced wx.PopupTransientWindow to wx.PopupWindow. This could solve the problem. I don’t have a Mac to check, so let me know if it doesn’t.