cogentcore / core

A free and open source framework for building powerful, fast, and elegant 2D and 3D apps that run on macOS, Windows, Linux, iOS, Android, and the Web with a single pure Go codebase, allowing you to Code Once, Run Everywhere.
http://cogentcore.org/core
BSD 3-Clause "New" or "Revised" License
1.32k stars 71 forks source link

Clean up bool functions, add panic safety checks, and start implementing the tree table widget #852

Closed ddkwork closed 5 months ago

ddkwork commented 5 months ago

I don't know how to specify the parent node when inserting a node like this example

go run github.com/richardwilkes/unison/example@latest

https://github.com/richardwilkes/unison/blob/main/example/demo/demo_table.go#L52-L91

rows := make([]*demoRow, topLevelRowsToMake) 
         for i := range rows { 
                 row := &demoRow{ 
                         table: table, 
                         id:    uuid.New(), 
                         text:  fmt.Sprintf("Row %d", i+1), 
                         text2: fmt.Sprintf("Some longer content for Row %d", i+1), 
                 } 
                 if i%10 == 3 { 
                         if i == 3 { 
                                 row.doubleHeight = true 
                         } 
                         row.container = true 
                         row.open = true 
                         row.children = make([]*demoRow, 5) 
                         for j := range row.children { 
                                 child := &demoRow{ 
                                         table:  table, 
                                         parent: row, 
                                         id:     uuid.New(), 
                                         text:   fmt.Sprintf("Sub Row %d", j+1), 
                                 } 
                                 row.children[j] = child 
                                 if j < 2 { 
                                         child.container = true 
                                         child.open = true 
                                         child.children = make([]*demoRow, 2) 
                                         for k := range child.children { 
                                                 child.children[k] = &demoRow{ 
                                                         table:  table, 
                                                         parent: child, 
                                                         id:     uuid.New(), 
                                                         text:   fmt.Sprintf("Sub Sub Row %d", k+1), 
                                                 } 
                                         } 
                                 } 
                         } 
                 } 
                 rows[i] = row 
         }

click: file-->new-->new demo table window

ddkwork commented 5 months ago

Please make a TreeTableView struct type that extends gi.Frame and then put most of your TreeTable function logic into a ConfigWidget method on TreeTableView.

It's better for you to modify the code, I've been looking at the implementation of the table for a long time, and the details of all the execution order, logic, events and drawings are all related together is still quite unfamiliar, but I will always study and learn your code implementation process, and strive to implement a widget myself one day, haha. At the moment I haven't done in-depth research and testing on the source code of the ki tree structure, I think this is a basic obstacle, and I guess the n-fork tree has some features ki should be added.

ddkwork commented 5 months ago

For tree structures, I feel that there are two ways to enter data: createItem and setRows, or pass in a struct slice directly, or pass in a tree struct directly, because its child nodes represent the slice meaning. The reason why we consider this is that there are several real-world scenarios that need to be done, for example: network packet capturer, when we classify the type of packets (top udp https websocket) nodes, each packet that is grabbed should be loaded into the gui immediately instead of waiting for all the packets to be retrieved before loading, which requires a CreatItem method to create a node, of course, it must be able to specify the parent node clearly, for example, when we catch an https packet, Then there is a TCP packet, and we should add the TCP packet to the TCP parent node before the HTTPS packet instead of to the HTTPS node, so that we can accurately classify it. The rest of the ERP software is also like this. Another scenario is to implement software such as an excel editor, in which case the node is created dynamically when editing excel, and when opening the edited file, it should be setrootRoows or pass in a deserialized struct.

kkoreilly commented 5 months ago

I will work on this and consider your points soon.

ddkwork commented 5 months ago

I will work on this and consider your points soon.

This is a widget that I am looking forward to, the tree table is quite intuitive to design any software, easy to understand, hierarchical, easy to categorize and summarize, I was thinking about a question: can we use the code folding and unfolding function of the code editor widget to control the code folding and unfolding function with the tree table widget, and the disassembly table of the hyperdbg debugger shows that if it is replaced with a tree table widget, then it should be easy to handle the hierarchy of assembly instructions, such as jnx xxx , call xxx,All these instructions will create a parent node with a child node,This simulates the expansion and collapse function of human disassembly,Similar can also try jsonView and protoBufView,This widget is really mind-blowing,haha 😃。

kkoreilly commented 5 months ago

Also, I reorganized the structure of apps some, so you should use gi.NewBody("App Name") instead of gi.NewAppBody("App Name") now.

ddkwork commented 5 months ago

Also, I reorganized the structure of apps some, so you should use gi.NewBody("App Name") instead of gi.NewAppBody("App Name") now.

Ok, I'm going to refresh all the code that calls core, and I'm removing all the previous programs that implemented the interface with UI libraries like Fyne, Wails, and Unison, and rewriting the interface with core. Thanks again to Core for this excellent design, which allowed me to focus more on backend development.

ddkwork commented 5 months ago

Also, I reorganized the structure of apps some, so you should use gi.NewBody("App Name") instead of gi.NewAppBody("App Name") now.

For the design of this widget, I feel that there is a problem with the previous combination widget logic, because each node of the tree should correspond to each row of the table, instead of generating a new table every time the node is selected, so I feel that I still have to re-implement the drawing of the tree table widget, and add some fields, such as ordinary node fields, container node fields, but this part of the logic seems to have been implemented in the tree widget, and I feel that the idea is getting more and more confused. Or mock some data and scenarios from unit tests to help ideate the logic

kkoreilly commented 5 months ago

I will work more on the tree table widget soon, and I will try to figure out a solution that resolves those issues. I will also write unit tests for it.

ddkwork commented 5 months ago

I will work more on the tree table widget soon, and I will try to figure out a solution that resolves those issues. I will also write unit tests for it.

I ported the network packet capture program, and found that the core still has a lot of bugs, and the fix I submitted at the moment is just to make the program run and no longer crash, if you have a more appropriate fix, please feel free to change. I think that when all the programs are ported, there will be fewer bugs in the core

ddkwork commented 5 months ago

In addition, the freetype repository has a problem of concurrent read and write of maps, if you can, please merge it into the core repository to facilitate PR

ddkwork commented 5 months ago

I've found that a lot of core's app sync packages use pointers, and I don't think they should be used. Here's an explanation to quote gpt: sync mutex is a struct type that contains a number of fields and methods. Because the sync mutex is a value type and not a reference type, it cannot be passed directly using pointers or references. In Go, value objects are copied when a function is called, so if you pass the sync mutex as a pointer, different mutex objects may be manipulated in different function calls, causing the lock to not work properly. Therefore, sync mutexes are generally used directly as value types.

In a bug fix I previously committed, I passed a mutex pointer externally and the main window never appeared, and the struct field of the table widget seems to generate a way to set the mutex pointer, which is in gtigen

kkoreilly commented 5 months ago

I will look into this. Also, I appreciate you cleaning up various functions, but in general we do not use one-line functions unless the function is incredibly simple, and we do not use named return variables unless there are several return values. Your boolean logic simplification changes are good though.

ddkwork commented 5 months ago

I will look into this. Also, I appreciate you cleaning up various functions, but in general we do not use one-line functions unless the function is incredibly simple, and we do not use named return variables unless there are several return values. Your boolean logic simplification changes are good though.

Ok, I'm going to make the changes as you ask, plus, please merge or deal with the last few bug-fixed PRs right away, otherwise the porters on my side will panic, and in addition, I'll make a PR to the freetype repository, which has a bug that causes panic

kkoreilly commented 5 months ago

I will merge this PR after you make the requested changes.

ddkwork commented 5 months ago

Please merge this pr https://github.com/goki/freetype/pull/6 and update the mod for core