714714-- OrdersSearchOverlay
715715--
716716
717- local search_matched_indices = {}
718- local search_current_match_idx = 0
719- local order_names_checksum = nil
717+ local ORDER_HEIGHT = 3
718+ local TABS_WIDTH_THRESHOLD = 155
719+ local LIST_START_Y_ONE_TABS_ROW = 8
720+ local LIST_START_Y_TWO_TABS_ROWS = 10
721+ local BOTTOM_MARGIN = 9
722+ local ARROW_X = 10
720723
721724local function perform_search (text )
722725 local matches = {}
@@ -750,6 +753,63 @@ local function calculate_order_names_checksum()
750753 return table.concat (names , " |" )
751754end
752755
756+ local function getListStartY ()
757+ local rect = gui .get_interface_rect ()
758+
759+ if rect .width >= TABS_WIDTH_THRESHOLD then
760+ return LIST_START_Y_ONE_TABS_ROW
761+ else
762+ return LIST_START_Y_TWO_TABS_ROWS
763+ end
764+ end
765+
766+ local function getViewportSize ()
767+ local rect = gui .get_interface_rect ()
768+ local list_start_y = getListStartY ()
769+
770+ local available_height = rect .height - list_start_y - BOTTOM_MARGIN
771+ return math.floor (available_height / ORDER_HEIGHT )
772+ end
773+
774+ local function getVisibleOrderIndices ()
775+ local orders = df .global .world .manager_orders .all
776+ local scroll_pos = mi .info .work_orders .scroll_position_work_orders
777+
778+ if # orders == 0 then return 0 , - 1 end
779+
780+ local viewport_size = getViewportSize ()
781+ local viewport_start = scroll_pos
782+ local viewport_end = scroll_pos + viewport_size - 1
783+
784+ -- Handle end-of-list case
785+ if viewport_end >= # orders then
786+ viewport_end = # orders - 1
787+ viewport_start = math.max (0 , viewport_end - viewport_size + 1 )
788+ end
789+
790+ return viewport_start , viewport_end
791+ end
792+
793+ local function calculateOrderY (order_idx )
794+ local orders = df .global .world .manager_orders .all
795+
796+ if # orders == 0 or order_idx < 0 or order_idx >= # orders then
797+ return nil
798+ end
799+
800+ local viewport_start , viewport_end = getVisibleOrderIndices ()
801+
802+ -- Check if order is in viewport
803+ if order_idx < viewport_start or order_idx > viewport_end then
804+ return nil
805+ end
806+
807+ local list_start_y = getListStartY ()
808+ local pos_in_viewport = order_idx - viewport_start
809+
810+ return list_start_y + (pos_in_viewport * ORDER_HEIGHT )
811+ end
812+
753813OrdersSearchOverlay = defclass (OrdersSearchOverlay , overlay .OverlayWidget )
754814OrdersSearchOverlay .ATTRS {
755815 desc = ' Adds a search box to find and navigate to matching manager orders.' ,
@@ -827,22 +887,25 @@ function OrdersSearchOverlay:init()
827887 }
828888
829889 self .minimized = false
890+ self .matched_indices = {}
891+ self .current_match_idx = 0
892+ self .order_names_checksum = nil
830893end
831894
832895function OrdersSearchOverlay :overlay_onupdate ()
833896 if self .minimized then return end
834897
835898 local new_checksum = calculate_order_names_checksum ()
836- if new_checksum ~= order_names_checksum then
837- order_names_checksum = new_checksum
899+ if new_checksum ~= self . order_names_checksum then
900+ self . order_names_checksum = new_checksum
838901 self :update_filter ()
839902 end
840903end
841904
842905function OrdersSearchOverlay :update_filter ()
843906 local text = self .subviews .filter .text
844- search_matched_indices = perform_search (text )
845- search_current_match_idx = 0
907+ self . matched_indices = perform_search (text )
908+ self . current_match_idx = 0
846909
847910 if text == ' ' then
848911 self .subviews .main_panel .frame_title = ' Search'
@@ -867,46 +930,46 @@ function OrdersSearchOverlay:cycle_match(direction)
867930 local new_matches = perform_search (search_text )
868931
869932 if # new_matches == 0 then
870- search_matched_indices = {}
871- search_current_match_idx = 0
933+ self . matched_indices = {}
934+ self . current_match_idx = 0
872935 self .subviews .main_panel .frame_title = ' Search'
873936 return
874937 end
875938
876- local new_match_idx = search_current_match_idx + direction
939+ local new_match_idx = self . current_match_idx + direction
877940
878941 if new_match_idx > # new_matches then
879942 new_match_idx = 1
880943 elseif new_match_idx < 1 then
881944 new_match_idx = # new_matches
882945 end
883946
884- search_matched_indices = new_matches
885- search_current_match_idx = new_match_idx
947+ self . matched_indices = new_matches
948+ self . current_match_idx = new_match_idx
886949
887950 -- Scroll to the selected match
888- local order_idx = search_matched_indices [ search_current_match_idx ]
951+ local order_idx = self . matched_indices [ self . current_match_idx ]
889952 mi .info .work_orders .scroll_position_work_orders = order_idx
890953
891954 self .subviews .main_panel .frame_title = ' Search' .. self :get_match_text ()
892955end
893956
894957function OrdersSearchOverlay :get_match_text ()
895- local total_matches = # search_matched_indices
958+ local total_matches = # self . matched_indices
896959
897960 if total_matches == 0 then
898961 return ' '
899962 end
900963
901- if search_current_match_idx == 0 then
964+ if self . current_match_idx == 0 then
902965 return string.format (' : %d matches' , total_matches )
903966 end
904967
905- return string.format (' : %d of %d' , search_current_match_idx , total_matches )
968+ return string.format (' : %d of %d' , self . current_match_idx , total_matches )
906969end
907970
908971function OrdersSearchOverlay :has_matches ()
909- return # search_matched_indices > 0
972+ return # self . matched_indices > 0
910973end
911974
912975local function is_mouse_key (keys )
@@ -955,88 +1018,11 @@ end
9551018function OrdersSearchOverlay :render (dc )
9561019 if mi .job_details .open then return end
9571020 OrdersSearchOverlay .super .render (self , dc )
1021+ self :render_highlights (dc )
9581022end
9591023
960- -- -------------------
961- -- OrderHighlightOverlay
962- -- -------------------
963-
964- local ORDER_HEIGHT = 3
965- local TABS_WIDTH_THRESHOLD = 155
966- local LIST_START_Y_ONE_TABS_ROW = 8
967- local LIST_START_Y_TWO_TABS_ROWS = 10
968- local BOTTOM_MARGIN = 9
969- local ARROW_X = 10
970-
971- local function getListStartY ()
972- local rect = gui .get_interface_rect ()
973-
974- if rect .width >= TABS_WIDTH_THRESHOLD then
975- return LIST_START_Y_ONE_TABS_ROW
976- else
977- return LIST_START_Y_TWO_TABS_ROWS
978- end
979- end
980-
981- local function getViewportSize ()
982- local rect = gui .get_interface_rect ()
983- local list_start_y = getListStartY ()
984-
985- local available_height = rect .height - list_start_y - BOTTOM_MARGIN
986- return math.floor (available_height / ORDER_HEIGHT )
987- end
988-
989- local function getVisibleOrderIndices ()
990- local orders = df .global .world .manager_orders .all
991- local scroll_pos = mi .info .work_orders .scroll_position_work_orders
992-
993- if # orders == 0 then return 0 , - 1 end
994-
995- local viewport_size = getViewportSize ()
996- local viewport_start = scroll_pos
997- local viewport_end = scroll_pos + viewport_size - 1
998-
999- -- Handle end-of-list case
1000- if viewport_end >= # orders then
1001- viewport_end = # orders - 1
1002- viewport_start = math.max (0 , viewport_end - viewport_size + 1 )
1003- end
1004-
1005- return viewport_start , viewport_end
1006- end
1007-
1008- local function calculateOrderY (order_idx )
1009- local orders = df .global .world .manager_orders .all
1010-
1011- if # orders == 0 or order_idx < 0 or order_idx >= # orders then
1012- return nil
1013- end
1014-
1015- local viewport_start , viewport_end = getVisibleOrderIndices ()
1016-
1017- -- Check if order is in viewport
1018- if order_idx < viewport_start or order_idx > viewport_end then
1019- return nil
1020- end
1021-
1022- local list_start_y = getListStartY ()
1023- local pos_in_viewport = order_idx - viewport_start
1024-
1025- return list_start_y + (pos_in_viewport * ORDER_HEIGHT )
1026- end
1027-
1028- OrderHighlightOverlay = defclass (OrderHighlightOverlay , overlay .OverlayWidget )
1029- OrderHighlightOverlay .ATTRS {
1030- desc = ' Shows arrows next to the work order found by orders.search' ,
1031- default_enabled = true ,
1032- viewscreens = ' dwarfmode/Info/WORK_ORDERS/Default' ,
1033- full_interface = true ,
1034- }
1035-
1036- function OrderHighlightOverlay :render (dc )
1037- OrderHighlightOverlay .super .render (self , dc )
1038-
1039- if mi .job_details .open or # search_matched_indices == 0 then return end
1024+ function OrdersSearchOverlay :render_highlights (dc )
1025+ if # self .matched_indices == 0 then return end
10401026
10411027 local selected_pen = dfhack .pen .parse {
10421028 fg = COLOR_BLACK ,
@@ -1050,16 +1036,13 @@ function OrderHighlightOverlay:render(dc)
10501036 bold = true ,
10511037 }
10521038
1053- -- Get the order index of the currently selected match
1054- local selected_order_idx = search_current_match_idx > 0 and
1055- search_matched_indices [search_current_match_idx ] or nil
1039+ local selected_order_idx = self .current_match_idx > 0 and
1040+ self .matched_indices [self .current_match_idx ] or nil
10561041
1057- -- Draw highlights for all matching orders in viewport
1058- for _ , match_order_idx in ipairs (search_matched_indices ) do
1042+ for _ , match_order_idx in ipairs (self .matched_indices ) do
10591043 local match_y = calculateOrderY (match_order_idx )
10601044
10611045 if match_y then
1062- -- Use red pen for selected match, white for others
10631046 local pen = (match_order_idx == selected_order_idx ) and selected_pen or match_pen
10641047
10651048 dc :seek (ARROW_X , match_y ):string (' |' , pen )
@@ -1075,7 +1058,6 @@ OVERLAY_WIDGETS = {
10751058 recheck = RecheckOverlay ,
10761059 importexport = OrdersOverlay ,
10771060 search = OrdersSearchOverlay ,
1078- highlight = OrderHighlightOverlay ,
10791061 skillrestrictions = SkillRestrictionOverlay ,
10801062 laborrestrictions = LaborRestrictionsOverlay ,
10811063 conditionsrightclick = ConditionsRightClickOverlay ,
0 commit comments