3939#include " base/math_util.hh"
4040#include " config.h"
4141
42+ static constexpr auto TIME_COLUMN_WIDTH = 22 ;
43+ static constexpr auto UNUSABLE_WIDTH = TIME_COLUMN_WIDTH + 2 ;
44+ static constexpr auto MINIMUM_WIDTH = UNUSABLE_WIDTH + 20 ;
45+
4246std::optional<size_t >
4347spectrogram_row::nearest_column (size_t current) const
4448{
@@ -77,7 +81,7 @@ spectrogram_source::list_input_handle_key(listview_curses& lv,
7781 }
7882
7983 auto [height, width] = lv.get_dimensions ();
80- width -= 2 ;
84+ width -= UNUSABLE_WIDTH ;
8185
8286 auto & sb = this ->ss_cached_bounds ;
8387 auto begin_time_opt = this ->time_for_row_int (sel.value ());
@@ -99,7 +103,10 @@ spectrogram_source::list_input_handle_key(listview_curses& lv,
99103 end_time,
100104 range_min,
101105 range_max);
106+ auto cursor_col = this ->ss_cursor_column ;
102107 this ->invalidate ();
108+ this ->ss_cursor_column = cursor_col;
109+ this ->text_selection_changed ((textview_curses&) lv);
103110 lv.reload_data ();
104111 return true ;
105112 }
@@ -125,13 +132,8 @@ spectrogram_source::list_input_handle_key(listview_curses& lv,
125132 case NCKEY_LEFT :
126133 case NCKEY_RIGHT : {
127134 auto sel = lv.get_selection ();
128- unsigned long width;
129- vis_line_t height;
130135 string_attrs_t sa;
131-
132- lv.get_dimensions (height, width);
133-
134- this ->text_attrs_for_line (
136+ this ->chart_attrs_for_line (
135137 (textview_curses&) lv, sel.value_or (0_vl), sa);
136138
137139 if (sa.empty ()) {
@@ -143,8 +145,9 @@ spectrogram_source::list_input_handle_key(listview_curses& lv,
143145 if (!this ->ss_cursor_column ) {
144146 lv.set_selection (0_vl);
145147 }
146- line_range lr (this ->ss_cursor_column .value (),
147- this ->ss_cursor_column .value () + 1 );
148+ line_range lr (
149+ TIME_COLUMN_WIDTH + this ->ss_cursor_column .value (),
150+ TIME_COLUMN_WIDTH + this ->ss_cursor_column .value () + 1 );
148151
149152 auto current = find_string_attr (sa, lr);
150153
@@ -168,7 +171,8 @@ spectrogram_source::list_input_handle_key(listview_curses& lv,
168171 current = sa.begin ();
169172 }
170173 }
171- this ->ss_cursor_column = current->sa_range .lr_start ;
174+ this ->ss_cursor_column
175+ = current->sa_range .lr_start - TIME_COLUMN_WIDTH ;
172176 this ->reset_details_source ();
173177
174178 lv.reload_data ();
@@ -187,10 +191,12 @@ spectrogram_source::text_handle_mouse(
187191 mouse_event& me)
188192{
189193 auto sel = tc.get_selection ();
190- if (!sel) {
194+ if (!sel || me. me_state != mouse_button_state_t :: BUTTON_STATE_RELEASED ) {
191195 return false ;
192196 }
193197 const auto & s_row = this ->load_row (tc, sel.value ());
198+ std::optional<size_t > closest_column;
199+ int closest_distance = INT_MAX ;
194200
195201 for (int lpc = 0 ; lpc <= (int ) s_row.sr_width ; lpc++) {
196202 int col_value = s_row.sr_values [lpc].rb_counter ;
@@ -199,16 +205,19 @@ spectrogram_source::text_handle_mouse(
199205 continue ;
200206 }
201207
202- auto lr = line_range{lpc, lpc + 1 };
203- if (me.is_click_in (mouse_button_t ::BUTTON_LEFT , lr)) {
204- this ->ss_cursor_column = lr.lr_start ;
205- this ->reset_details_source ();
206-
207- tc.reload_data ();
208- return true ;
208+ auto distance = std::abs (me.me_x - (TIME_COLUMN_WIDTH + lpc));
209+ if (distance < closest_distance) {
210+ closest_distance = distance;
211+ closest_column = lpc;
209212 }
210213 }
211214
215+ if (closest_column) {
216+ this ->ss_cursor_column = closest_column;
217+ this ->reset_details_source ();
218+ tc.reload_data ();
219+ return true ;
220+ }
212221 return false ;
213222}
214223
@@ -218,7 +227,7 @@ spectrogram_source::list_value_for_overlay(const listview_curses& lv,
218227 std::vector<attr_line_t >& value_out)
219228{
220229 auto [height, width] = lv.get_dimensions ();
221- width -= 2 ;
230+ width -= UNUSABLE_WIDTH ;
222231
223232 const auto sel = lv.get_selection ();
224233 if (sel && row == sel.value () && this ->ss_cursor_column ) {
@@ -262,7 +271,7 @@ spectrogram_source::list_value_for_overlay(const listview_curses& lv,
262271 .append (lnav::roles::number (
263272 fmt::format (FMT_STRING (" {:.2Lf}" ), range_max)))
264273 .append (" " );
265- auto mark_offset = this ->ss_cursor_column .value ();
274+ auto mark_offset = TIME_COLUMN_WIDTH + this ->ss_cursor_column .value ();
266275 auto mark_is_before = true ;
267276
268277 retval.al_attrs .emplace_back (line_range{0 , -1 },
@@ -353,7 +362,7 @@ spectrogram_source::time_for_row(vis_line_t row)
353362std::optional<text_time_translator::row_info>
354363spectrogram_source::time_for_row_int (vis_line_t row)
355364{
356- timeval retval{0 , 0 };
365+ auto retval = timeval {0 , 0 };
357366
358367 this ->cache_bounds ();
359368 retval.tv_sec = to_time_t (
@@ -390,9 +399,13 @@ spectrogram_source::text_value_for_line(textview_curses& tc,
390399 std::string& value_out,
391400 text_sub_source::line_flags_t flags)
392401{
402+ if (tc.get_dimensions ().second < MINIMUM_WIDTH ) {
403+ return {};
404+ }
405+
393406 const auto & s_row = this ->load_row (tc, row);
394407 char tm_buffer[128 ];
395- struct tm tm;
408+ tm tm;
396409
397410 auto row_time_opt = this ->time_for_row_int (vis_line_t (row));
398411 if (!row_time_opt) {
@@ -405,26 +418,22 @@ spectrogram_source::text_value_for_line(textview_curses& tc,
405418 strftime (tm_buffer, sizeof (tm_buffer), " %a %b %d %H:%M:%S" , &tm);
406419
407420 value_out = tm_buffer;
408- value_out.resize (s_row.sr_width , ' ' );
421+ value_out.resize (TIME_COLUMN_WIDTH + s_row.sr_width , ' ' );
409422
410423 for (size_t lpc = 0 ; lpc <= s_row.sr_width ; lpc++) {
411424 if (s_row.sr_values [lpc].rb_marks ) {
412- value_out[lpc] = ' x' ;
425+ value_out[TIME_COLUMN_WIDTH + lpc] = ' x' ;
413426 }
414427 }
415428
416429 return {};
417430}
418431
419432void
420- spectrogram_source::text_attrs_for_line (textview_curses& tc,
421- int row,
422- string_attrs_t & value_out)
433+ spectrogram_source::chart_attrs_for_line (textview_curses& tc,
434+ int row,
435+ string_attrs_t & value_out)
423436{
424- if (this ->ss_value_source == nullptr ) {
425- return ;
426- }
427-
428437 const auto & st = this ->ss_cached_thresholds ;
429438 const auto & s_row = this ->load_row (tc, row);
430439
@@ -444,8 +453,26 @@ spectrogram_source::text_attrs_for_line(textview_curses& tc,
444453 } else {
445454 role = role_t ::VCR_HIGH_THRESHOLD ;
446455 }
447- value_out.emplace_back (line_range (lpc, lpc + 1 ), VC_ROLE .value (role));
456+ auto lr
457+ = line_range{TIME_COLUMN_WIDTH + lpc, TIME_COLUMN_WIDTH + lpc + 1 };
458+ value_out.emplace_back (lr, VC_ROLE .value (role));
448459 }
460+ }
461+
462+ void
463+ spectrogram_source::text_attrs_for_line (textview_curses& tc,
464+ int row,
465+ string_attrs_t & value_out)
466+ {
467+ if (this ->ss_value_source == nullptr ) {
468+ return ;
469+ }
470+
471+ if (tc.get_dimensions ().second < MINIMUM_WIDTH ) {
472+ return ;
473+ }
474+
475+ this ->chart_attrs_for_line (tc, row, value_out);
449476
450477 auto alt_row_index = row % 4 ;
451478 if (alt_row_index == 2 || alt_row_index == 3 ) {
@@ -522,11 +549,8 @@ spectrogram_source::load_row(const listview_curses& tc, int row)
522549{
523550 this ->cache_bounds ();
524551
525- unsigned long width;
526- vis_line_t height;
527-
528- tc.get_dimensions (height, width);
529- width -= 2 ;
552+ auto [height, width] = tc.get_dimensions ();
553+ width -= UNUSABLE_WIDTH ;
530554
531555 auto & sb = this ->ss_cached_bounds ;
532556 spectrogram_request sr (sb);
@@ -597,13 +621,17 @@ spectrogram_source::list_static_overlay(const listview_curses& lv,
597621 if (y != 0 ) {
598622 return false ;
599623 }
624+ auto [height, width] = lv.get_dimensions ();
625+
626+ if (width < MINIMUM_WIDTH ) {
627+ value_out = lnav::console::user_message::error (
628+ " window is too narrow, not able to show chart" )
629+ .to_attr_line ();
630+ return true ;
631+ }
600632
601633 auto & line = value_out.get_string ();
602- vis_line_t height;
603- unsigned long width;
604634 char buf[128 ];
605-
606- lv.get_dimensions (height, width);
607635 width -= 2 ;
608636
609637 this ->cache_bounds ();
@@ -619,8 +647,9 @@ spectrogram_source::list_static_overlay(const listview_curses& lv,
619647 auto & sb = this ->ss_cached_bounds ;
620648 auto & st = this ->ss_cached_thresholds ;
621649
650+ line.append (TIME_COLUMN_WIDTH , ' ' );
622651 snprintf (buf, sizeof (buf), " Min: %'.10lg" , sb.sb_min_value_out );
623- line = buf;
652+ line. append ( buf) ;
624653
625654 snprintf (buf,
626655 sizeof (buf),
0 commit comments