From 988b88f875372c944a83c66de7812447a7b3552a Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Fri, 21 Oct 2022 18:36:03 -0700 Subject: [PATCH] DeskTop: Allow selection in list views This constitutes two changes: * Adds support to IconTK for a "small icon" flag where the icon is in-line with and the same height as the label. * Reworks DeskTop to use "small icons" for the list view, effectively as an overlay on top of the other columns. Because all views now have icons, this actually removes many special cases and saves bytes in main memory. Room for future improvement: * Selection is lost when changing view type. This is not a regression since it was previously lost anyway, but would be nice to fix. * Renaming an icon when View > by Name is selected causes the window to refresh to reflect the new sort order. Ditto. * Now that list views are not useless, it would be nice to save/restore the view type in addition to the window bounds across restarts. Resolves #28 --- RELEASE-NOTES.md | 1 + desktop/internal.inc | 7 +- desktop/main.s | 402 +++++++++++++++++++----------------------- desktop/res.s | 46 ++++- res/notes/icons.txt | 34 ++++ res/notes/testplan.md | 10 ++ toolkits/IconTK.md | 2 +- toolkits/icontk.inc | 3 +- toolkits/icontk.s | 88 ++++++++- 9 files changed, 362 insertions(+), 231 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index e9d67396..ab8269fa 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -22,6 +22,7 @@ Project Page: https://github.com/a2stuff/a2d * CD-ROM drives now shown with a CD icon. * Unhighlight more correctly when dragging icons over folders. * Show keyboard shortcut for File > Delete in menu. +* Support selection in list views. ([#28](https://github.com/a2stuff/a2d/issues/28)) ### Disk Copy diff --git a/desktop/internal.inc b/desktop/internal.inc index 4e6e37a9..dab97ab2 100644 --- a/desktop/internal.inc +++ b/desktop/internal.inc @@ -71,9 +71,12 @@ kWindowHeaderHeight = 14 ;;; -------------------------------------------------- ;;; List views -kFirstRowBaseline = 16 +kListViewInitialTop = kWindowHeaderHeight + kIconBBoxPaddingTop +kListViewInitialLeft = 4 + +kListViewFirstBaseline = kListViewInitialTop - 2 kListViewWidth = 410 -kListViewRowHeight = kSystemFontHeight + 1 +kListViewRowHeight = kListItemHeight ;;; -------------------------------------------------- ;;; Icon views diff --git a/desktop/main.s b/desktop/main.s index b9d87fad..c3ae9ff6 100644 --- a/desktop/main.s +++ b/desktop/main.s @@ -2346,16 +2346,7 @@ ret: rts stax tmp ; name - ;; Icon view? - tya ; window id - beq :+ ; 0=desktop (so yes) - tax - lda win_view_by_table-1,x - bpl :+ - lda #0 ; list view = not found - rts - -: jsr PushPointers + jsr PushPointers copy16 tmp, ptr_name sty cached_window_id @@ -2729,7 +2720,9 @@ ResetHandler := CmdQuitImpl::ResetHandler ;;; ============================================================ -.proc CmdViewByIcon +.proc ViewByCommon + sta view + ;; Valid? lda active_window_id bne :+ @@ -2737,27 +2730,41 @@ ResetHandler := CmdQuitImpl::ResetHandler : ;; Is this a change? jsr GetActiveWindowViewBy + cmp view bne :+ ; not by icon rts : - -;;; Entry point when refreshing window contents -entry: ;; Update view menu/table - lda #kViewByIcon + view := *+1 + lda #SELF_MODIFIED_BYTE ldx active_window_id sta win_view_by_table-1,x jsr UpdateViewMenuCheck + ;; Destroy existing icons +entry2: + jsr DestroyIconsInActiveWindow + +;;; Entry point when refreshing window contents +entry3: + ;; Clear selection if in the window + lda selected_window_id + cmp active_window_id + bne :+ + lda #0 + sta selected_icon_count + sta selected_window_id +: ;; Reset the viewport jsr ResetActiveWindowViewport ; Must precede icon creation ;; Create the icons jsr LoadActiveWindowEntryTable jsr InitCachedWindowEntries - ;; NOTE: Could call `SortRecords` here with A=kViewBy* - - lda cached_window_id + jsr GetCachedWindowViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_NEG + jsr SortRecords + END_IF jsr CreateIconsForWindow jsr StoreWindowEntryTable jsr AddIconsForCachedWindow @@ -2787,55 +2794,6 @@ entry: ;;; ============================================================ -.proc ViewByNoniconCommon - sta view - - ;; Valid? - lda active_window_id - bne :+ - rts -: - ;; Is this a change? - jsr GetActiveWindowViewBy - cmp view - bne :+ - rts -: - ;; Destroy existing icons - cmp #kViewByIcon - bne :+ - jsr DestroyIconsInActiveWindow -: - ;; Update view menu/table - view := *+1 - lda #SELF_MODIFIED_BYTE - ldx active_window_id - sta win_view_by_table-1,x - jsr UpdateViewMenuCheck - - ;; Clear selection if in the window - lda selected_window_id - cmp active_window_id - bne sort - lda #0 - sta selected_icon_count - sta selected_window_id - - ;; Sort the records -sort: jsr LoadActiveWindowEntryTable - jsr InitCachedWindowEntries - jsr GetCachedWindowViewBy - jsr SortRecords - jsr StoreWindowEntryTable - - ;; Reset the viewport - jsr ResetActiveWindowViewport - - FALL_THROUGH_TO RedrawAfterContentChange -.endproc - -;;; ============================================================ - .proc RedrawAfterContentChange ;; Draw the contents lda active_window_id @@ -2850,32 +2808,39 @@ sort: jsr LoadActiveWindowEntryTable .endproc +;;; ============================================================ + +.proc CmdViewByIcon + lda #kViewByIcon + jmp ViewByCommon +.endproc + ;;; ============================================================ .proc CmdViewByName lda #kViewByName - jmp ViewByNoniconCommon + jmp ViewByCommon .endproc ;;; ============================================================ .proc CmdViewByDate lda #kViewByDate - jmp ViewByNoniconCommon + jmp ViewByCommon .endproc ;;; ============================================================ .proc CmdViewBySize lda #kViewBySize - jmp ViewByNoniconCommon + jmp ViewByCommon .endproc ;;; ============================================================ .proc CmdViewByType lda #kViewByType - jmp ViewByNoniconCommon + jmp ViewByCommon .endproc ;;; ============================================================ @@ -3020,6 +2985,14 @@ CmdLock := DoLock jsr DoRename sta result + ;; If selection is in a window with View > by Name, refresh + jsr GetSelectionViewBy + cmp #kViewByName + bne :+ + txa + jmp ViewByCommon::entry2 +: + bit result bpl :+ ; N = window renamed ;; TODO: Avoid repainting everything @@ -3277,9 +3250,6 @@ typedown_buf: lda active_window_id beq volumes ; no active window - jsr GetActiveWindowViewBy - bmi volumes ; not icon view - ;; -------------------------------------------------- ;; Icons in active window @@ -3481,13 +3451,7 @@ ret: rts beq :+ jsr ClearSelection -: lda active_window_id - beq :+ ; desktop is okay - jsr GetActiveWindowViewBy - bpl :+ ; view by icons - rts - -: jsr LoadActiveWindowEntryTable + jsr LoadActiveWindowEntryTable lda cached_window_entry_count jeq finish ; nothing to select! @@ -3688,19 +3652,18 @@ tick_v: .byte 0 _Preamble: jsr LoadActiveWindowEntryTable - jsr GetActiveWindowViewBy - IF_POS - ;; Icon view + jsr CachedIconsScreenToWindow jsr ComputeIconsBBox jsr CachedIconsWindowToScreen + jsr GetActiveWindowViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_POS + ;; Icon view copy #kIconViewScrollTickH, tick_h copy #kIconViewScrollTickV, tick_v ELSE ;; List view - jsr ComputeIconsBBox - copy #kListViewScrollTickH, tick_h copy #kListViewScrollTickV, tick_v END_IF @@ -4550,9 +4513,6 @@ bail: return #$FF ; high bit set = not repeating bcs :+ rts : - jsr GetActiveWindowViewBy - jmi ClearSelection ; not icons - copy active_window_id, findicon_params::window_id ITK_CALL IconTK::FindIcon, findicon_params lda findicon_params::which_icon @@ -4835,13 +4795,11 @@ exception_flag: jsr RemoveWindowFilerecordEntries ;; Remove old icons - jsr GetActiveWindowViewBy - bmi :+ ; list view, not icons jsr DestroyIconsInActiveWindow jsr ClearActiveWindowEntryCount ;; Copy window path to `src_path_buf` -: lda active_window_id + lda active_window_id jsr GetWindowPath jsr CopyToSrcPath @@ -4850,7 +4808,7 @@ exception_flag: jsr OpenDirectory ;; Create icons and draw contents - jsr CmdViewByIcon::entry + jsr ViewByCommon::entry3 ;; Draw header lda active_window_id @@ -4860,14 +4818,6 @@ exception_flag: jsr DrawWindowHeader END_IF - ;; Set view state and update menu - lda #0 - ldx active_window_id - sta win_view_by_table-1,x - - copy #1, menu_click_params::item_num - jsr UpdateViewMenuCheck - rts .endproc @@ -5088,19 +5038,15 @@ last_pos: copy active_window_id, dragwindow_params::window_id - jsr GetActiveWindowViewBy - bmi :+ jsr LoadActiveWindowEntryTable jsr CachedIconsScreenToWindow -: + MGTK_CALL MGTK::DragWindow, dragwindow_params ;; `dragwindow_params::moved` is not checked; harmless if it didn't. - jsr GetActiveWindowViewBy - bmi :+ jsr CachedIconsWindowToScreen jsr StoreWindowEntryTable -: + rts .endproc @@ -5145,9 +5091,6 @@ last_pos: jsr ClearSelection - jsr GetCachedWindowViewBy - IF_NC - ;; Icon view lda icon_count sec sbc cached_window_entry_count @@ -5156,7 +5099,6 @@ last_pos: ITK_CALL IconTK::RemoveAll, cached_window_id jsr FreeCachedWindowIcons - END_IF dec num_open_windows copy #0, cached_window_entry_count @@ -5318,23 +5260,10 @@ done: rts rts .endproc -;;; Safe to call even if not an icon view .proc AssignActiveWindowCliprectAndUpdateCachedIcons - - jsr GetActiveWindowViewBy - pha - IF_POS jsr CachedIconsScreenToWindow - END_IF - jsr AssignActiveWindowCliprect - - pla - IF_POS - jsr CachedIconsWindowToScreen - END_IF - - rts + jmp CachedIconsWindowToScreen .endproc @@ -5916,7 +5845,6 @@ kDrawWindowEntriesContentOnly = $40 kDrawWindowEntriesContentOnlyPortAdjusted = $80 .proc DrawWindowEntries - ptr := $06 sta header_and_offset_flag jsr PushPointers @@ -5940,14 +5868,28 @@ kDrawWindowEntriesContentOnlyPortAdjusted = $80 END_IF END_IF - ;; List or Icon view? + ;; -------------------------------------------------- + ;; Icons - jsr GetCachedWindowViewBy - jpl icon_view + ;; Map icons to window space + jsr CachedIconsScreenToWindow + + ITK_CALL IconTK::DrawAll, cached_window_id + +.if DEBUG + jsr ComputeIconsBBox + COPY_STRUCT MGTK::Rect, iconbb_rect, tmp_rect + jsr FrameTmpRect +.endif + + ;; Map icons back to screen space + jsr CachedIconsWindowToScreen ;; -------------------------------------------------- - ;; List view -list_view: + ;; List View Columns + + jsr GetCachedWindowViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + bpl done ;; Find FileRecord list lda cached_window_id @@ -5956,19 +5898,10 @@ list_view: inc16 file_record_ptr ; now points at first entry in list ;; First row - - lda #kFirstRowBaseline - sta pos_col_icon::ycoord - sta pos_col_name::ycoord - sta pos_col_type::ycoord - sta pos_col_size::ycoord - sta pos_col_date::ycoord - lda #0 - sta pos_col_icon::ycoord+1 - sta pos_col_name::ycoord+1 - sta pos_col_type::ycoord+1 - sta pos_col_size::ycoord+1 - sta pos_col_date::ycoord+1 + ldax #kListViewFirstBaseline + stax pos_col_type::ycoord + stax pos_col_size::ycoord + stax pos_col_date::ycoord ;; Draw each list view row lda #0 @@ -5979,22 +5912,17 @@ rloop: lda #SELF_MODIFIED_BYTE beq done tax lda cached_window_entry_list,x - jsr DrawListViewRow - inc rows_done - jmp rloop - - ;; -------------------------------------------------- - ;; Icon view -icon_view: - ;; Map icons to window space - jsr CachedIconsScreenToWindow - - ITK_CALL IconTK::DrawAll, cached_window_id + ;; Look up file record number + ptr := $06 + jsr IconEntryLookup + stax ptr + ldy #IconEntry::record_num + lda (ptr),y - ;; Map icons back to screen space - jsr CachedIconsWindowToScreen - jmp done + jsr DrawListViewRowZeroBased + inc rows_done + jmp rloop ;; -------------------------------------------------- done: @@ -7088,7 +7016,6 @@ volume: ldx cached_window_id jsr InitCachedWindowEntries ;; NOTE: Could call `SortRecords` here with A=kViewBy* - lda cached_window_id jsr CreateIconsForWindow jsr StoreWindowEntryTable jsr AddIconsForCachedWindow @@ -7110,11 +7037,10 @@ copy_new_window_bounds_flag: ;;; ============================================================ ;;; File Icon Entry Construction -;;; Inputs: A = window_id +;;; Inputs: `cached_window_id` must be set .proc CreateIconsForWindowImpl -window_id: .byte 0 iconbits: .addr 0 iconentry_flags: .byte 0 icon_height: .word 0 @@ -7132,9 +7058,18 @@ icons_this_row: DEFINE_POINT icon_coords, 0, 0 .proc Start - sta window_id jsr PushPointers + jsr GetCachedWindowViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_NEG + ;; List View + copy16 #kListViewInitialLeft, row_coords::xcoord + copy16 #kListViewInitialTop, row_coords::ycoord + copy16 #kListViewInitialLeft, initial_xcoord + copy #1, icons_per_row ; by definition + copy #0, col_spacing ; N/A + copy #kListItemHeight, row_spacing + ELSE ;; Icon View copy16 #kIconViewInitialLeft, row_coords::xcoord copy16 #kIconViewInitialTop, row_coords::ycoord @@ -7142,6 +7077,7 @@ icons_this_row: copy #kIconViewIconsPerRow, icons_per_row copy #kIconViewSpacingX, col_spacing copy #kIconViewSpacingY, row_spacing + END_IF lda #0 sta icons_this_row @@ -7259,8 +7195,13 @@ records_base_ptr: bit LCBANK1 bit LCBANK1 + jsr GetCachedWindowViewBy + sta view_by jsr GetIconType + view_by := *+1 + ldy #SELF_MODIFIED_BYTE jsr FindIconDetailsForIconType + ldy #IconEntry::name ldx #0 L77F0: lda name_tmp,x @@ -7282,9 +7223,12 @@ L77F0: lda name_tmp,x cpx #.sizeof(MGTK::Point) bne :- - ;; Include y-offset + jsr GetCachedWindowViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_POS + ;; Icon view: include y-offset ldy #IconEntry::icony sub16in (icon_entry),y, icon_height, (icon_entry),y + END_IF lda cached_window_entry_count cmp icons_per_row @@ -7343,27 +7287,50 @@ L7870: lda cached_window_id .endproc ;;; ============================================================ -;;; Inputs: A = `IconType` member +;;; Inputs: A = `IconType` member, Y = `kViewByXXX` value ;;; Outputs: Populates `iconentry_flags`, `iconbits`, `icon_height` .proc FindIconDetailsForIconType ptr := $6 + sty view_by jsr PushPointers - ;; For populating IconEntry::win_flags - tay - lda icontype_iconentryflags_table, y + ;; For populating `IconEntry::win_flags` + tay ; Y = `IconType` + lda icontype_iconentryflags_table,y sta iconentry_flags - ;; For populating IconEntry::iconbits - tya + ;; Load up A,X with pointer to `IconResource` + view_by := *+1 + lda #SELF_MODIFIED_BYTE + cmp #kViewByIcon + IF_NE + ;; List View + lda iconentry_flags + ora #kIconEntryFlagsSmall + sta iconentry_flags + + ldax #sm_gen + cpy #IconType::folder + IF_EQ + ldax #sm_dir + END_IF + ELSE + ;; Icon View + tya ; Y = `IconType` asl a tay - copy16 type_icons_table,y, iconbits + lda type_icons_table,y + ldx type_icons_table+1,y + END_IF + + ;; For populating IconEntry::iconbits + stax iconbits ;; Icon height will be needed too - copy16 iconbits, ptr + stax ptr +set_height: ldy #IconResource::maprect + MGTK::Rect::y2 copy16in (ptr),y, icon_height @@ -7752,6 +7719,7 @@ xcoord: ;;; ============================================================ ;;; Compute bounding box for icons within cached window +;;; Inputs: `cached_window_id` is set DEFINE_RECT iconbb_rect, 0, 0, 0, 0 @@ -7772,44 +7740,10 @@ start: ;; icon_num = 0 sta icon_num - ;; Icon view? - jsr GetCachedWindowViewBy - bpl icon_view ; icon view - - ;; -------------------------------------------------- - ;; List view - - ;; max.y = A * kListViewRowHeight + kWindowHeaderHeight+2 - lda cached_window_entry_count - pha ; A = count - ldx #0 ; A,X = count + 2 - ldy #kListViewRowHeight - jsr Multiply_16_8_16 - addax #kWindowHeaderHeight+2, iconbb_rect::y2 - - ;; max.x = count > 0 ? kListViewWidth : 0 - pla ; A = count - IF_NOT_ZERO - copy16 #kListViewWidth, iconbb_rect::x2 - END_IF - - ;; min.y = kWindowHeaderHeight - copy16 #kWindowHeaderHeight, iconbb_rect::y1 - - ;; min.x = 0 (initialized above) - rts - - - ;; -------------------------------------------------- - ;; Icon view -icon_view: ;; min.x = min.y = kIntMax - lda #kIntMax - sta iconbb_rect::x1+1 - sta iconbb_rect+MGTK::Rect::y1+1 + ldax #kIntMax + stax iconbb_rect::x1 + stax iconbb_rect+MGTK::Rect::y1 check_icon: icon_num := *+1 @@ -7818,20 +7752,34 @@ check_icon: bne more finish: + ;; If there are any entries... + lda cached_window_entry_count + IF_NOT_ZERO ;; Add padding around bbox sub16_8 iconbb_rect::x1, #kIconBBoxPaddingLeft add16_8 iconbb_rect::x2, #kIconBBoxPaddingRight sub16_8 iconbb_rect::y1, #kIconBBoxPaddingTop add16_8 iconbb_rect::y2, #kIconBBoxPaddingBottom + ;; List view? + jsr GetCachedWindowViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_NEG + ;; max.x = kListViewWidth + copy16 #kListViewWidth, iconbb_rect::x2 + END_IF + END_IF + rts more: lda cached_window_entry_list,x sta icon_param ITK_CALL IconTK::GetIconBounds, icon_param ; inits `tmp_rect` + jsr GetCachedWindowViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_POS ;; Pretend icon is max height sub16 tmp_rect::y2, #kMaxIconTotalHeight, tmp_rect::y1 + END_IF ;; First icon (index 0) - just use its coordinates as min/max lda icon_num @@ -8210,6 +8158,8 @@ found: txa tax ; 1-based to 0-based dex txa + +ep_zero_based: .assert .sizeof(FileRecord) = 32, error, "FileRecord size must be 2^5" jsr ATimes32 ; A,X = A * 32 addax file_record_ptr, ptr @@ -8226,30 +8176,20 @@ found: txa bit LCBANK1 ;; Below bottom? - scmp16 pos_col_name::ycoord, window_grafport::maprect::y2 + scmp16 pos_col_type::ycoord, window_grafport::maprect::y2 bpl ret - add16_8 pos_col_icon::ycoord, #kListViewRowHeight - add16_8 pos_col_name::ycoord, #kListViewRowHeight add16_8 pos_col_type::ycoord, #kListViewRowHeight add16_8 pos_col_size::ycoord, #kListViewRowHeight add16_8 pos_col_date::ycoord, #kListViewRowHeight ;; Above top? - scmp16 pos_col_name::ycoord, window_grafport::maprect::y1 + scmp16 pos_col_type::ycoord, window_grafport::maprect::y1 bpl in_range ret: rts ;; Draw it! in_range: - MGTK_CALL MGTK::MoveTo, pos_col_icon - jsr PrepareColGlyph - jsr draw_text - - MGTK_CALL MGTK::MoveTo, pos_col_name - jsr PrepareColName - jsr draw_text - MGTK_CALL MGTK::MoveTo, pos_col_type jsr PrepareColType jsr draw_text @@ -8266,6 +8206,7 @@ draw_text: MGTK_CALL MGTK::DrawText, text_buffer2 rts .endproc +DrawListViewRowZeroBased := DrawListViewRow::ep_zero_based ;;; ============================================================ @@ -11001,8 +10942,11 @@ finish: lda #RenameDialogState::close stax icon_ptr ;; Compute bounds of icon bitmap + jsr GetSelectionViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_POS ITK_CALL IconTK::GetIconBounds, icon_param ; inits `tmp_rect` sub16_8 tmp_rect::y2, #kIconLabelHeight + kIconLabelGap, tmp_rect::y2 + END_IF ldy #IconEntry::record_num lda (icon_ptr),y @@ -11045,7 +10989,12 @@ finish: lda #RenameDialogState::close bit LCBANK1 bit LCBANK1 + jsr GetSelectionViewBy ; N=0/Z=1 is icon view, N=1/Z=0 is list view + IF_POS + sta view_by jsr GetIconType + view_by := *+1 + ldy #SELF_MODIFIED_BYTE jsr CreateIconsForWindowImpl::FindIconDetailsForIconType ;; Use new `icon_height` to offset vertically. @@ -11056,6 +11005,8 @@ finish: lda #RenameDialogState::close ldy #IconEntry::iconbits copy16in CreateIconsForWindowImpl::iconbits, (icon_ptr),y ;; Assumes `iconentry_flags` will not change, regardless of icon. + END_IF + end_filerecord_and_icon_update: ;; Draw the (maybe new) icon @@ -15096,20 +15047,29 @@ done: rts ;;; ============================================================ ;;; Outputs: A = kViewBy* value for active window ;;; If kViewByIcon, Z=1 and N=0; otherwise Z=0 and N=1 -;;; Assert: There is an active/cached window +;;; Assert: There is an active window .proc GetActiveWindowViewBy ldx active_window_id lda win_view_by_table-1,x rts .endproc +;;; Assert: There is a cached window .proc GetCachedWindowViewBy ldx cached_window_id lda win_view_by_table-1,x rts .endproc +;;; Assert: There is a selection. +;;; NOTE: This variant works even if selection is on desktop +.proc GetSelectionViewBy + ldx selected_window_id + lda win_view_by_table-1,x + rts +.endproc + ;;; ============================================================ .proc ToggleMenuHilite diff --git a/desktop/res.s b/desktop/res.s index 13582614..9d031c0c 100644 --- a/desktop/res.s +++ b/desktop/res.s @@ -704,11 +704,12 @@ window_title_addr_table: .addr winfo8title ASSERT_ADDRESS_TABLE_SIZE window_title_addr_table, kMaxNumWindows + 1 +;;; `win_view_by_table` is indexed by window id - 1; allow referencing +;;; the desktop (window id 0), which is always icon view. + .byte kViewByIcon win_view_by_table: .res kMaxNumWindows, 0 - DEFINE_POINT pos_col_icon, kListViewIconX, 0 - DEFINE_POINT pos_col_name, kListViewNameX, 0 DEFINE_POINT pos_col_type, 128, 0 DEFINE_POINT pos_col_size, 166, 0 DEFINE_POINT pos_col_date, 231, 0 @@ -1366,6 +1367,47 @@ app_mask: .byte PX(%0000000),PX(%0000000),PX(%1111110),PX(%0000000),PX(%0000000) .byte PX(%0000000),PX(%0000000),PX(%0011000),PX(%0000000),PX(%0000000) +;;; Small Icons - use for "View > by XXXX" +;;; Same visibility rules as above. +;;; NOTE: Keep in sync with kGlyphFile* and kGlyphFolder* in the system fonts. + + DEFINE_ICON_RESOURCE sm_gen, generic_sm_icon, 2, 13, 7, generic_sm_mask + DEFINE_ICON_RESOURCE sm_dir, folder_sm_icon, 2, 13, 6, folder_sm_mask +generic_sm_icon: + .byte PX(%0011111),PX(%1000000) + .byte PX(%0010000),PX(%1110000) + .byte PX(%0010000),PX(%1111100) + .byte PX(%0010000),PX(%0000100) + .byte PX(%0010000),PX(%0000100) + .byte PX(%0010000),PX(%0000100) + .byte PX(%0010000),PX(%0000100) + .byte PX(%0011111),PX(%1111100) +generic_sm_mask: + .byte PX(%0011111),PX(%1000000) + .byte PX(%0011111),PX(%1110000) + .byte PX(%0011111),PX(%1111100) + .byte PX(%0011111),PX(%1111100) + .byte PX(%0011111),PX(%1111100) + .byte PX(%0011111),PX(%1111100) + .byte PX(%0011111),PX(%1111100) + .byte PX(%0011111),PX(%1111100) +folder_sm_icon: + .byte PX(%0111110),PX(%0000000) + .byte PX(%1000001),PX(%1111110) + .byte PX(%1000000),PX(%0000001) + .byte PX(%1000000),PX(%0000001) + .byte PX(%1000000),PX(%0000001) + .byte PX(%1000000),PX(%0000001) + .byte PX(%1111111),PX(%1111111) +folder_sm_mask: + .byte PX(%0111110),PX(%0000000) + .byte PX(%1111111),PX(%1111110) + .byte PX(%1111111),PX(%1111111) + .byte PX(%1111111),PX(%1111111) + .byte PX(%1111111),PX(%1111111) + .byte PX(%1111111),PX(%1111111) + .byte PX(%1111111),PX(%1111111) + ;;; ============================================================ PAD_TO ::kSegmentDeskTopLC1AAddress + ::kSegmentDeskTopLC1ALength diff --git a/res/notes/icons.txt b/res/notes/icons.txt index 878cd6c9..6beb7ddb 100644 --- a/res/notes/icons.txt +++ b/res/notes/icons.txt @@ -416,3 +416,37 @@ Tiger Learning Computer (maybe some day...) #### #### | ############ | ------------------------------------- + ##### | +# ####### | +# #| +# #| +# #| +# #| +##############| +--------------- + ###### | + # ### | + # ##### | + # # | + # # | + # # | + # # | + ########## | +--------------- + ##### | +############# | +##############| +##############| +##############| +##############| +##############| +--------------- + ###### | + ######## | + ########## | + ########## | + ########## | + ########## | + ########## | + ########## | +--------------- diff --git a/res/notes/testplan.md b/res/notes/testplan.md index e1ed3a70..cee6791a 100644 --- a/res/notes/testplan.md +++ b/res/notes/testplan.md @@ -408,6 +408,16 @@ * Launch DeskTop. On a volume, create folders named "A1", "B1", "A", and "B". View > by Name. Verify that the order is: "A", "A1", "B", "B1". +* Launch DeskTop. Open window containing icons. View > by Name. Verify that selection is supported: + * The icon bitmap and name can be clicked on. + * Drag-selecting the icon bitmap and/or name selects. + * Selected icons can be dragged to other windows or volume icons to initiate a move or copy. + * Dragging a selected icon over a non-selected folder icon in the same window causes it to highlight, and initiates a move or copy (depending on modifier keys). +* Launch DeskTop. Open window containing icons. View > by Name. Select one or more icons. Drag them within the window but not over any other icons. Release the mouse button. Verify that the icons do not move. +* Launch DeskTop. Open window containing icons. View > by Name. Rename an icon, picking a name that would change the ordering. Verify that the window is refreshed and the icons are correctly sorted by name. +* Launch DeskTop. Open a window containing a folder. Open a folder. Activate the parent window and verify that the folder's icon is dimmed. View > by Name. Verify that the folder's icon is still dimmed. View > as Icons. Verify that the folder's icon is still dimmed. +* Launch DeskTop. Open a window containing a folder. View > by Name. Verify that the folder's icon is dimmed. View > as Icon. Verify that the folder's icon is still dimmed. + ## Shortcuts * Set up multiple volumes (e.g. V1, V2, V3). Launch DeskTop. Use Shortcuts > Add a Shortcut... to add an shortcut on V2. Run Shortcuts > Edit a Shortcut... and select the added shortcut to edit it, which should init the dialog showing V2. Click Change Drive. Verify that the picker now shows V3. diff --git a/toolkits/IconTK.md b/toolkits/IconTK.md index bf6c34cc..9559eed5 100644 --- a/toolkits/IconTK.md +++ b/toolkits/IconTK.md @@ -24,7 +24,7 @@ This defines an icon instance. bit 6 = highlighted .byte type/window_id bits 0-3 = window_id - bit 4 = unused + bit 4 = small icon (for list views) bit 5 = not valid drop source flag (i.e. trash) bit 6 = drop target flag (trash, folder, dir) bit 7 = open flag diff --git a/toolkits/icontk.inc b/toolkits/icontk.inc index 280be01b..0244e766 100644 --- a/toolkits/icontk.inc +++ b/toolkits/icontk.inc @@ -63,7 +63,7 @@ label := * ;;; $00 if not allocated ;;; .byte flags/window_id ;;; bits 0-3 = window_id -;;; bit 4 = unused +;;; bit 4 = small icon (list view) ;;; bit 5 = not valid drop source flag (i.e. trash) ;;; bit 6 = drop target flag (trash, folder, dir) ;;; bit 7 = dimmed flag @@ -96,6 +96,7 @@ kIconEntryStateHighlighted = %01000000 kIconEntryFlagsDimmed = %10000000 kIconEntryFlagsDropTarget = %01000000 kIconEntryFlagsNotDropSource = %00100000 +kIconEntryFlagsSmall = %00010000 kIconEntryWinIdMask = %00001111 .struct IconResource diff --git a/toolkits/icontk.s b/toolkits/icontk.s index a8b6e785..7a121db6 100644 --- a/toolkits/icontk.s +++ b/toolkits/icontk.s @@ -138,6 +138,9 @@ result: .word 0 .endparams settextbg_params := textwidth_params::result + 1 ; re-used +settextbg_white: + .byte MGTK::textbg_white + .params drawtext_params textptr: .addr text_buffer textlen: .byte 0 @@ -1029,6 +1032,15 @@ includes_trash: ;; Drag within same window (or desktop) same_window: + + ;; Small icons have a fixed layout + ldy highlight_list + copylohi icon_ptrs_low,y, icon_ptrs_high,y, $06 + ldy #IconEntry::win_flags + lda ($06),y + and #kIconEntryFlagsSmall + bne L9C63 ; don't move + ldx highlight_count : dex bmi :+ @@ -1756,6 +1768,8 @@ no_clip_vol_icons_flag: MGTK_CALL MGTK::DrawText, drawtext_params MGTK_CALL MGTK::ShowCursor + MGTK_CALL MGTK::SetTextBG, settextbg_white + return #0 .proc Shade @@ -1805,16 +1819,37 @@ kIconLabelGapV = 2 dex bpl :- - ;; ---------------------------------------- - ;; Regular icon - ;; Bitmap bottom/right ldy #IconResource::maprect + MGTK::Rect::x2 add16in bitmap_rect::x1, (bitmap_ptr),y, bitmap_rect::x2 - .assert (MGTK::Rect::y2 - MGTK::Rect::x2) = 2, error, "y2 must be 2 more than x2" iny add16in bitmap_rect::y1, (bitmap_ptr),y, bitmap_rect::y2 + ldy #IconEntry::win_flags + lda (entry_ptr),y + and #kIconEntryFlagsSmall + IF_NOT_ZERO + ;; ---------------------------------------- + ;; Small icon + + ;; Label top + copy16 bitmap_rect::y1, label_rect::y1 + + ;; Label bottom + add16_8 label_rect::y1, #kSystemFontHeight+1, label_rect::y2 + + ;; Left edge of label + add16_8 bitmap_rect::x2, #kListViewIconGap-2, label_rect::x1 + + ;; Label right + add16 label_rect::x1, textwidth_params::result, label_rect::x2 + + ;; Force bitmap bottom to same height + copy16 label_rect::y2, bitmap_rect::y2 + ELSE + ;; ---------------------------------------- + ;; Regular icon + ;; Label top add16_8 bitmap_rect::y2, #kIconLabelGapV, label_rect::y1 @@ -1837,6 +1872,8 @@ kIconLabelGapV = 2 ;; Label right add16 label_rect::x1, textwidth_params::result, label_rect::x2 + END_IF + jsr PopPointers ; do not tail-call optimise! rts .endproc @@ -1886,6 +1923,47 @@ kIconPolySize = (8 * .sizeof(MGTK::Point)) + 2 jsr CalcIconBoundingRect + ldy #IconEntry::win_flags + lda (entry_ptr),y + and #kIconEntryFlagsSmall + IF_NOT_ZERO + ;; ---------------------------------------- + ;; Small icon + + ;; v0/v1/v2/v3/v4 v5 + ;; +-----------------------+ + ;; | | + ;; | | + ;; +-----------------------+ + ;; v7 v6 + + ;; Start off making all (except v6) the same + ldy #.sizeof(MGTK::Point)-1 +: lda bitmap_rect::topleft,y + sta poly::v0,y + sta poly::v1,y + sta poly::v2,y + sta poly::v3,y + sta poly::v4,y + sta poly::v5,y + sta poly::v7,y + dey + bpl :- + + ;; Then tweak remaining vertices on right/bottom + ldax label_rect::x2 + stax poly::v5::xcoord + stax poly::v6::xcoord + + ldax bitmap_rect::y2 + stax poly::v6::ycoord + stax poly::v7::ycoord + + ELSE + + ;; ---------------------------------------- + ;; Normal icon + ;; v0 v1 ;; +----------+ ;; | | @@ -1927,6 +2005,8 @@ kIconPolySize = (8 * .sizeof(MGTK::Point)) + 2 ;; ---------------------------------------- + END_IF + jsr PopPointers ; do not tail-call optimise! rts .endproc