@@ -56,6 +56,7 @@ EVT_LIST_ITEM_ACTIVATED(wxID_HARDDISK, MainFrameDerived::OnOpenProject)
5656EVT_LIST_ITEM_SELECTED(wxID_HARDDISK, MainFrameDerived::OnSelectProject)
5757EVT_LIST_ITEM_DESELECTED(wxID_HARDDISK, MainFrameDerived::OnDeselectProject)
5858EVT_LIST_DELETE_ITEM(wxID_HARDDISK, MainFrameDerived::OnDeselectProject)
59+ EVT_LIST_COL_CLICK(wxID_HARDDISK, MainFrameDerived::OnColumnClick)
5960
6061EVT_LISTBOX(wxID_FLOPPY, MainFrameDerived::OnSelectEditor)
6162EVT_LISTBOX(wxID_HOME, MainFrameDerived::OnSelectEditorPath)
@@ -167,7 +168,10 @@ void MainFrameDerived::ReloadData(){
167168 editors.clear ();
168169
169170 LoadProjects (" " );
170-
171+
172+ // Sort projects after loading (default: by name ascending)
173+ SortProjects ();
174+
171175 // check that the installs path file exists in the folder
172176 auto p = datapath / editorPathsFile;
173177 if (filesystem::exists (p)){
@@ -225,7 +229,8 @@ void MainFrameDerived::Filter(wxKeyEvent &event){
225229 projectsList->SetItemState (0 , wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED, wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED);
226230
227231 // open first item
228- OpenProject (0 );
232+ long projectIndex = projectsList->GetItemData (0 );
233+ OpenProject (projectIndex);
229234 return ;
230235 }
231236 }
@@ -236,6 +241,8 @@ void MainFrameDerived::Filter(wxKeyEvent &event){
236241 auto filter = projSearchCtrl->GetValue ().ToStdString ();
237242 transform (filter.begin (), filter.end (), filter.begin (), ::tolower);
238243 LoadProjects (filter);
244+ // Re-apply sorting after filtering
245+ SortProjects ();
239246}
240247
241248#define BUILD_YEAR (__DATE__ + 7 )
@@ -366,7 +373,8 @@ void MainFrameDerived::OnCreateProject(wxCommandEvent& event){
366373void MainFrameDerived::OnRevealProject (wxCommandEvent& event){
367374 long selectedIndex = wxListCtrl_get_selected (projectsList);
368375 if (selectedIndex > -1 ){
369- project& p = projects[selectedIndex];
376+ long projectIndex = projectsList->GetItemData (selectedIndex);
377+ project& p = projects[projectIndex];
370378 reveal_in_explorer (p.path );
371379 }
372380}
@@ -377,12 +385,13 @@ void MainFrameDerived::OnRevealProject(wxCommandEvent& event){
377385void MainFrameDerived::OnOpenWith (wxCommandEvent& event){
378386 long selectedIndex = wxListCtrl_get_selected (projectsList);
379387 if (selectedIndex > -1 ){
380- project& p = projects[selectedIndex];
388+ long projectIndex = projectsList->GetItemData (selectedIndex);
389+ project& p = projects[projectIndex];
381390 OpenWithCallback c = [&](project p, editor e, TargetPlatform plat){
382391 // open the project
383392 OpenProject (p,e, plat);
384393 };
385-
394+
386395 OpenWithDlg* dlg = new OpenWithDlg (this ,p,editors,c);
387396 dlg->show ();
388397 }
@@ -554,30 +563,45 @@ void MainFrameDerived::AddProject(const project& p, const std::string& filter, b
554563 auto name = p.name ;
555564 transform (name.begin (), name.end (), name.begin (), ::tolower);
556565 if (name.find (filter) != std::string::npos){
566+ // Get the index where we're adding the project
567+ size_t projectIndex = projects.size ();
557568 projects.push_back (p);
558-
569+
559570 // save to file
560571 if (save){
561572 SaveProjects ();
562573 }
563-
574+
564575 // add to the UI
565576 wxListItem i;
566577 i.SetId (projectsList->GetItemCount ());
567578 i.SetText (p.name );
568- projectsList->InsertItem (i);
569- projectsList->SetItem (i, 1 , p.version );
570- projectsList->SetItem (i, 2 , p.modifiedDate );
571- projectsList->SetItem (i, 3 , p.path .string ());
572-
579+ long itemIndex = projectsList->InsertItem (i);
580+
581+ // Store the project index as item data
582+ projectsList->SetItemData (itemIndex, projectIndex);
583+
584+ projectsList->SetItem (itemIndex, 1 , p.version );
585+ projectsList->SetItem (itemIndex, 2 , p.modifiedDate );
586+ projectsList->SetItem (itemIndex, 3 , p.path .string ());
587+
573588 // resize columns
574589 int cols = projectsList->GetColumnCount ();
575- for (int i = 0 ; i < cols; i ++){
576- projectsList->SetColumnWidth (i , wxLIST_AUTOSIZE_USEHEADER);
590+ for (int j = 0 ; j < cols; j ++){
591+ projectsList->SetColumnWidth (j , wxLIST_AUTOSIZE_USEHEADER);
577592 }
578-
593+
594+ // Sort the list to place the new item in the correct position
595+ SortProjects ();
596+
579597 if (select){
580- projectsList->SetItemState (i, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
598+ // Find the item after sorting
599+ for (int k = 0 ; k < projectsList->GetItemCount (); k++) {
600+ if (projectsList->GetItemData (k) == static_cast <long >(projectIndex)) {
601+ projectsList->SetItemState (k, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
602+ break ;
603+ }
604+ }
581605 }
582606 }
583607
@@ -684,5 +708,66 @@ void MainFrameDerived::OnUninstall(wxCommandEvent &){
684708 ShellExecute (0 , 0 , uninstaller_path.c_str (), NULL , 0 , SW_SHOW);
685709#endif
686710 }
687-
711+ }
712+
713+ // Handle column click for sorting
714+ void MainFrameDerived::OnColumnClick (wxListEvent& event) {
715+ int col = event.GetColumn ();
716+
717+ // If clicking the same column, toggle sort direction
718+ if (col == sortColumn) {
719+ sortAscending = !sortAscending;
720+ } else {
721+ sortColumn = col;
722+ // For date column, default to descending (newest first)
723+ // For other columns, default to ascending
724+ sortAscending = (col != 2 );
725+ }
726+
727+ SortProjects ();
728+ }
729+
730+ // Sort comparison function
731+ int wxCALLBACK MainFrameDerived::CompareItems (wxIntPtr item1, wxIntPtr item2, wxIntPtr sortData) {
732+ MainFrameDerived* frame = reinterpret_cast <MainFrameDerived*>(sortData);
733+
734+ // Get the actual project indices
735+ const project& p1 = frame->projects [item1];
736+ const project& p2 = frame->projects [item2];
737+
738+ int result = 0 ;
739+
740+ switch (frame->sortColumn ) {
741+ case 0 : // Name
742+ result = p1.name .compare (p2.name );
743+ break ;
744+ case 1 : // Version
745+ result = p1.version .compare (p2.version );
746+ break ;
747+ case 2 : // Last Modified
748+ // Compare dates - note: string comparison may not work correctly for all date formats
749+ // For dates, default to newest first (reverse the comparison)
750+ result = p2.modifiedDate .compare (p1.modifiedDate );
751+ break ;
752+ case 3 : // Path
753+ result = p1.path .string ().compare (p2.path .string ());
754+ break ;
755+ }
756+
757+ // If items are equal on primary sort, sort by name
758+ if (result == 0 && frame->sortColumn != 0 ) {
759+ result = p1.name .compare (p2.name );
760+ }
761+
762+ // Apply sort direction
763+ if (!frame->sortAscending ) {
764+ result = -result;
765+ }
766+
767+ return result;
768+ }
769+
770+ // Sort the project list
771+ void MainFrameDerived::SortProjects () {
772+ projectsList->SortItems (CompareItems, reinterpret_cast <wxIntPtr>(this ));
688773}
0 commit comments