ColumnsPanel.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. htop - ColumnsPanel.c
  3. (C) 2004-2011 Hisham H. Muhammad
  4. Released under the GNU GPLv2+, see the COPYING file
  5. in the source distribution for its full text.
  6. */
  7. #include "config.h" // IWYU pragma: keep
  8. #include "ColumnsPanel.h"
  9. #include <assert.h>
  10. #include <ctype.h>
  11. #include <stdlib.h>
  12. #include "CRT.h"
  13. #include "DynamicColumn.h"
  14. #include "FunctionBar.h"
  15. #include "Hashtable.h"
  16. #include "ListItem.h"
  17. #include "Object.h"
  18. #include "Process.h"
  19. #include "ProvideCurses.h"
  20. #include "RowField.h"
  21. #include "XUtils.h"
  22. static const char* const ColumnsFunctions[] = {" ", " ", " ", " ", " ", " ", "MoveUp", "MoveDn", "Remove", "Done ", NULL};
  23. static void ColumnsPanel_delete(Object* object) {
  24. Panel* super = (Panel*) object;
  25. ColumnsPanel* this = (ColumnsPanel*) object;
  26. Panel_done(super);
  27. free(this);
  28. }
  29. static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
  30. ColumnsPanel* const this = (ColumnsPanel*) super;
  31. int selected = Panel_getSelectedIndex(super);
  32. HandlerResult result = IGNORED;
  33. int size = Panel_size(super);
  34. switch (ch) {
  35. case 0x0a:
  36. case 0x0d:
  37. case KEY_ENTER:
  38. case KEY_MOUSE:
  39. case KEY_RECLICK:
  40. if (selected < size - 1) {
  41. this->moving = !(this->moving);
  42. Panel_setSelectionColor(super, this->moving ? PANEL_SELECTION_FOLLOW : PANEL_SELECTION_FOCUS);
  43. ListItem* selectedItem = (ListItem*) Panel_getSelected(super);
  44. if (selectedItem)
  45. selectedItem->moving = this->moving;
  46. result = HANDLED;
  47. }
  48. break;
  49. case KEY_UP:
  50. if (!this->moving)
  51. break;
  52. /* else fallthrough */
  53. case KEY_F(7):
  54. case '[':
  55. case '-':
  56. if (selected < size - 1)
  57. Panel_moveSelectedUp(super);
  58. result = HANDLED;
  59. break;
  60. case KEY_DOWN:
  61. if (!this->moving)
  62. break;
  63. /* else fallthrough */
  64. case KEY_F(8):
  65. case ']':
  66. case '+':
  67. if (selected < size - 2)
  68. Panel_moveSelectedDown(super);
  69. result = HANDLED;
  70. break;
  71. case KEY_F(9):
  72. case KEY_DC:
  73. if (selected < size - 1)
  74. Panel_remove(super, selected);
  75. result = HANDLED;
  76. break;
  77. default:
  78. if (0 < ch && ch < 255 && isgraph((unsigned char)ch))
  79. result = Panel_selectByTyping(super, ch);
  80. if (result == BREAK_LOOP)
  81. result = IGNORED;
  82. break;
  83. }
  84. if (result == HANDLED)
  85. ColumnsPanel_update(super);
  86. return result;
  87. }
  88. const PanelClass ColumnsPanel_class = {
  89. .super = {
  90. .extends = Class(Panel),
  91. .delete = ColumnsPanel_delete
  92. },
  93. .eventHandler = ColumnsPanel_eventHandler
  94. };
  95. static void ColumnsPanel_add(Panel* super, unsigned int key, Hashtable* columns) {
  96. const char* name;
  97. if (key < LAST_PROCESSFIELD) {
  98. name = Process_fields[key].name;
  99. } else {
  100. const DynamicColumn* column = Hashtable_get(columns, key);
  101. assert(column);
  102. if (!column) {
  103. name = NULL;
  104. } else {
  105. /* heading preferred here but name is always available */
  106. name = column->heading ? column->heading : column->name;
  107. }
  108. }
  109. if (name == NULL)
  110. name = "- ";
  111. Panel_add(super, (Object*) ListItem_new(name, key));
  112. }
  113. void ColumnsPanel_fill(ColumnsPanel* this, ScreenSettings* ss, Hashtable* columns) {
  114. Panel* super = (Panel*) this;
  115. Panel_prune(super);
  116. for (const RowField* fields = ss->fields; *fields; fields++)
  117. ColumnsPanel_add(super, *fields, columns);
  118. this->ss = ss;
  119. }
  120. ColumnsPanel* ColumnsPanel_new(ScreenSettings* ss, Hashtable* columns, bool* changed) {
  121. ColumnsPanel* this = AllocThis(ColumnsPanel);
  122. Panel* super = (Panel*) this;
  123. FunctionBar* fuBar = FunctionBar_new(ColumnsFunctions, NULL, NULL);
  124. Panel_init(super, 1, 1, 1, 1, Class(ListItem), true, fuBar);
  125. this->ss = ss;
  126. this->changed = changed;
  127. this->moving = false;
  128. Panel_setHeader(super, "Active Columns");
  129. ColumnsPanel_fill(this, ss, columns);
  130. return this;
  131. }
  132. void ColumnsPanel_update(Panel* super) {
  133. ColumnsPanel* this = (ColumnsPanel*) super;
  134. int size = Panel_size(super);
  135. *(this->changed) = true;
  136. this->ss->fields = xRealloc(this->ss->fields, sizeof(ProcessField) * (size + 1));
  137. this->ss->flags = 0;
  138. for (int i = 0; i < size; i++) {
  139. int key = ((ListItem*) Panel_get(super, i))->key;
  140. this->ss->fields[i] = key;
  141. if (key < LAST_PROCESSFIELD)
  142. this->ss->flags |= Process_fields[key].flags;
  143. }
  144. this->ss->fields[size] = 0;
  145. }