ListBox.cs 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (c) 2004 Novell, Inc.
  21. //
  22. // Authors:
  23. // Jordi Mas i Hernandez, [email protected]
  24. //
  25. // TODO:
  26. // - Keyboard navigation
  27. // - Horizontal item scroll
  28. // - Performance testing
  29. //
  30. //
  31. // NOT COMPLETE
  32. using System;
  33. using System.Drawing;
  34. using System.Collections;
  35. using System.ComponentModel;
  36. using System.Reflection;
  37. namespace System.Windows.Forms
  38. {
  39. public class ListBox : ListControl
  40. {
  41. internal class ListBoxInfo
  42. {
  43. internal int item_height; /* Item's height */
  44. internal int top_item; /* First item that we show the in the current page */
  45. internal int last_item; /* Last visible item */
  46. internal int page_size; /* Number of listbox items per page. In MultiColumn listbox indicates items per column */
  47. internal Rectangle textdrawing_rect; /* Displayable Client Rectangle minus the scrollbars and with IntegralHeight calculated*/
  48. internal bool show_verticalsb; /* Is Vertical scrollbar show it? */
  49. internal bool show_horizontalsb; /* Is Horizontal scrollbar show it? */
  50. internal Rectangle client_rect; /* Client Rectangle. Usually = ClientRectangle except when IntegralHeight has been applied*/
  51. internal int max_itemwidth; /* Maxium item width within the listbox */
  52. public ListBoxInfo ()
  53. {
  54. last_item = 0;
  55. item_height = 0;
  56. top_item = 0;
  57. page_size = 0;
  58. max_itemwidth = 0;
  59. show_verticalsb = false;
  60. show_horizontalsb = false;
  61. }
  62. }
  63. internal class ListBoxItem
  64. {
  65. internal int Index;
  66. internal bool Selected;
  67. internal int ItemHeight; /* Only used for OwnerDrawVariable */
  68. internal CheckState State;
  69. public ListBoxItem (int index)
  70. {
  71. Index = index;
  72. Selected = false;
  73. ItemHeight = -1;
  74. State = CheckState.Unchecked;
  75. }
  76. }
  77. internal enum ItemNavigation
  78. {
  79. First,
  80. Last,
  81. Next,
  82. Previous,
  83. NextPage,
  84. PreviousPage,
  85. PreviousColumn,
  86. NextColumn
  87. }
  88. private BorderStyle border_style;
  89. private int column_width;
  90. private DrawMode draw_mode;
  91. private int horizontal_extent;
  92. private bool horizontal_scrollbar;
  93. private bool integral_height;
  94. private bool multicolumn;
  95. private bool scroll_always_visible;
  96. private int selected_index;
  97. private SelectedIndexCollection selected_indices;
  98. private SelectedObjectCollection selected_items;
  99. private SelectionMode selection_mode;
  100. private bool sorted;
  101. private bool use_tabstops;
  102. private int preferred_height;
  103. private int top_index;
  104. private int column_width_internal;
  105. private VScrollBar vscrollbar_ctrl;
  106. private HScrollBar hscrollbar_ctrl;
  107. private bool suspend_ctrlupdate;
  108. private bool ctrl_pressed;
  109. private bool shift_pressed;
  110. private bool has_focus;
  111. internal int focused_item;
  112. internal StringFormat string_format;
  113. internal ListBoxInfo listbox_info;
  114. internal ObjectCollection items;
  115. public ListBox ()
  116. {
  117. border_style = BorderStyle.Fixed3D;
  118. draw_mode = DrawMode.Normal;
  119. horizontal_extent = 0;
  120. horizontal_scrollbar = false;
  121. integral_height = true;
  122. multicolumn = false;
  123. preferred_height = 7;
  124. scroll_always_visible = false;
  125. selected_index = -1;
  126. focused_item = -1;
  127. selection_mode = SelectionMode.One;
  128. sorted = false;
  129. top_index = 0;
  130. use_tabstops = true;
  131. BackColor = ThemeEngine.Current.ColorWindow;
  132. ColumnWidth = 0;
  133. suspend_ctrlupdate = false;
  134. ctrl_pressed = false;
  135. shift_pressed = false;
  136. has_focus = false;
  137. items = new ObjectCollection (this);
  138. selected_indices = new SelectedIndexCollection (this);
  139. selected_items = new SelectedObjectCollection (this);
  140. listbox_info = new ListBoxInfo ();
  141. string_format = new StringFormat ();
  142. listbox_info.item_height = FontHeight;
  143. /* Vertical scrollbar */
  144. vscrollbar_ctrl = new VScrollBar ();
  145. vscrollbar_ctrl.Minimum = 0;
  146. vscrollbar_ctrl.SmallChange = 1;
  147. vscrollbar_ctrl.LargeChange = 1;
  148. vscrollbar_ctrl.Maximum = 0;
  149. vscrollbar_ctrl.ValueChanged += new EventHandler (VerticalScrollEvent);
  150. vscrollbar_ctrl.Visible = false;
  151. /* Horizontal scrollbar */
  152. hscrollbar_ctrl = new HScrollBar ();
  153. hscrollbar_ctrl.Minimum = 0;
  154. hscrollbar_ctrl.SmallChange = 1;
  155. hscrollbar_ctrl.LargeChange = 1;
  156. hscrollbar_ctrl.Maximum = 0;
  157. hscrollbar_ctrl.Visible = false;
  158. hscrollbar_ctrl.ValueChanged += new EventHandler (HorizontalScrollEvent);
  159. /* Events */
  160. MouseDown += new MouseEventHandler (OnMouseDownLB);
  161. KeyDown += new KeyEventHandler (OnKeyDownLB);
  162. KeyUp += new KeyEventHandler (OnKeyUpLB);
  163. GotFocus += new EventHandler (OnGotFocus);
  164. LostFocus += new EventHandler (OnLostFocus);
  165. UpdateFormatString ();
  166. }
  167. #region Events
  168. public new event EventHandler BackgroundImageChanged;
  169. public new event EventHandler Click;
  170. public event DrawItemEventHandler DrawItem;
  171. public event MeasureItemEventHandler MeasureItem;
  172. public new event PaintEventHandler Paint;
  173. public event EventHandler SelectedIndexChanged;
  174. public new event EventHandler TextChanged;
  175. #endregion // Events
  176. #region Public Properties
  177. public override Color BackColor {
  178. get { return base.BackColor; }
  179. set {
  180. if (base.BackColor == value)
  181. return;
  182. base.BackColor = value;
  183. base.Refresh (); // Careful. Calling the base method is not the same that calling
  184. } // the overriden one that refresh also all the items
  185. }
  186. public override Image BackgroundImage {
  187. get { return base.BackgroundImage; }
  188. set {
  189. if (base.BackgroundImage == value)
  190. return;
  191. base.BackgroundImage = value;
  192. if (BackgroundImageChanged != null)
  193. BackgroundImageChanged (this, EventArgs.Empty);
  194. base.Refresh ();
  195. }
  196. }
  197. public BorderStyle BorderStyle {
  198. get { return border_style; }
  199. set {
  200. if (!Enum.IsDefined (typeof (BorderStyle), value))
  201. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for BorderStyle", value));
  202. if (border_style == value)
  203. return;
  204. border_style = value;
  205. base.Refresh ();
  206. }
  207. }
  208. public int ColumnWidth {
  209. get { return column_width; }
  210. set {
  211. if (column_width < 0)
  212. throw new ArgumentException ("A value less than zero is assigned to the property.");
  213. column_width = value;
  214. if (value == 0)
  215. ColumnWidthInternal = 120;
  216. else
  217. ColumnWidthInternal = value;
  218. base.Refresh ();
  219. }
  220. }
  221. protected override CreateParams CreateParams {
  222. get { return base.CreateParams;}
  223. }
  224. protected override Size DefaultSize {
  225. get { return new Size (120, 96); }
  226. }
  227. public virtual DrawMode DrawMode {
  228. get { return draw_mode; }
  229. set {
  230. if (!Enum.IsDefined (typeof (DrawMode), value))
  231. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for DrawMode", value));
  232. if (value == DrawMode.OwnerDrawVariable && multicolumn == true)
  233. throw new InvalidEnumArgumentException ("Cannot have variable height and multicolumn");
  234. if (draw_mode == value)
  235. return;
  236. draw_mode = value;
  237. base.Refresh ();
  238. }
  239. }
  240. public override Color ForeColor {
  241. get { return base.ForeColor; }
  242. set {
  243. if (base.ForeColor == value)
  244. return;
  245. base.ForeColor = value;
  246. base.Refresh ();
  247. }
  248. }
  249. public int HorizontalExtent {
  250. get { return horizontal_extent; }
  251. set {
  252. if (horizontal_extent == value)
  253. return;
  254. horizontal_extent = value;
  255. base.Refresh ();
  256. }
  257. }
  258. public bool HorizontalScrollbar {
  259. get { return horizontal_scrollbar; }
  260. set {
  261. if (horizontal_scrollbar == value)
  262. return;
  263. horizontal_scrollbar = value;
  264. UpdateShowHorizontalScrollBar ();
  265. base.Refresh ();
  266. }
  267. }
  268. public bool IntegralHeight {
  269. get { return integral_height; }
  270. set {
  271. if (integral_height == value)
  272. return;
  273. integral_height = value;
  274. CalcClientArea ();
  275. }
  276. }
  277. public virtual int ItemHeight {
  278. get { return listbox_info.item_height; }
  279. set {
  280. if (value > 255)
  281. throw new ArgumentOutOfRangeException ("The ItemHeight property was set beyond 255 pixels");
  282. listbox_info.item_height = value;
  283. CalcClientArea ();
  284. }
  285. }
  286. public ObjectCollection Items {
  287. get { return items; }
  288. }
  289. public bool MultiColumn {
  290. get { return multicolumn; }
  291. set {
  292. if (multicolumn == value)
  293. return;
  294. if (value == true && DrawMode == DrawMode.OwnerDrawVariable)
  295. throw new ArgumentException ("A multicolumn ListBox cannot have a variable-sized height.");
  296. multicolumn = value;
  297. UpdateShowVerticalScrollBar (); /* the needs for scrollbars may change */
  298. UpdateShowHorizontalScrollBar ();
  299. base.Refresh ();
  300. }
  301. }
  302. public int PreferredHeight {
  303. get { return preferred_height;}
  304. }
  305. public override RightToLeft RightToLeft {
  306. get { return base.RightToLeft; }
  307. set {
  308. if (base.RightToLeft == value)
  309. return;
  310. base.RightToLeft = value;
  311. UpdateFormatString ();
  312. base.Refresh ();
  313. }
  314. }
  315. // Only afects the Vertical ScrollBar
  316. public bool ScrollAlwaysVisible {
  317. get { return scroll_always_visible; }
  318. set {
  319. if (scroll_always_visible == value)
  320. return;
  321. scroll_always_visible = value;
  322. UpdateShowVerticalScrollBar ();
  323. UpdateShowHorizontalScrollBar ();
  324. }
  325. }
  326. public override int SelectedIndex {
  327. get { return selected_index;}
  328. set {
  329. if (value < -1 || value >= Items.Count)
  330. throw new ArgumentOutOfRangeException ("Index of out range");
  331. if (SelectionMode == SelectionMode.None)
  332. throw new ArgumentException ("cannot call this method if SelectionMode is SelectionMode.None");
  333. if (selected_index == value)
  334. return;
  335. if (SelectionMode == SelectionMode.One)
  336. UnSelectItem (selected_index, true);
  337. SelectItem (value);
  338. selected_index = value;
  339. focused_item = value;
  340. OnSelectedIndexChanged (new EventArgs ());
  341. }
  342. }
  343. public SelectedIndexCollection SelectedIndices {
  344. get { return selected_indices; }
  345. }
  346. public object SelectedItem {
  347. get {
  348. if (SelectedItems.Count > 0)
  349. return SelectedItems[0];
  350. else
  351. return null;
  352. }
  353. set {
  354. int index = Items.IndexOf (value);
  355. if (index == -1)
  356. return;
  357. if (index != SelectedIndex) {
  358. SelectedIndex = index;
  359. }
  360. }
  361. }
  362. public SelectedObjectCollection SelectedItems {
  363. get {return selected_items;}
  364. }
  365. public virtual SelectionMode SelectionMode {
  366. get { return selection_mode; }
  367. set {
  368. if (!Enum.IsDefined (typeof (SelectionMode), value))
  369. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for SelectionMode", value));
  370. if (selection_mode == value)
  371. return;
  372. selection_mode = value;
  373. base.Refresh ();
  374. }
  375. }
  376. public bool Sorted {
  377. get { return sorted; }
  378. set {
  379. if (sorted == value)
  380. return;
  381. sorted = value;
  382. Sort ();
  383. }
  384. }
  385. public override string Text {
  386. get {
  387. if (SelectionMode != SelectionMode.None && SelectedIndex != -1)
  388. return Items[SelectedIndex].ToString ();
  389. return base.Text;
  390. }
  391. set {
  392. base.Text = value;
  393. if (SelectionMode == SelectionMode.None)
  394. return;
  395. int index;
  396. index = FindStringExact (value);
  397. if (index == -1)
  398. return;
  399. SelectedIndex = index;
  400. }
  401. }
  402. public int TopIndex {
  403. get { return top_index;}
  404. set {
  405. if (value == top_index)
  406. return;
  407. if (value < 0 || value >= Items.Count)
  408. return;
  409. value = top_index;
  410. base.Refresh ();
  411. }
  412. }
  413. public bool UseTabStops {
  414. get { return use_tabstops; }
  415. set {
  416. if (use_tabstops == value)
  417. return;
  418. use_tabstops = value;
  419. UpdateFormatString ();
  420. base.Refresh ();
  421. }
  422. }
  423. #endregion Public Properties
  424. #region Private Properties
  425. internal ListBoxInfo LBoxInfo {
  426. get { return listbox_info; }
  427. }
  428. private int ColumnWidthInternal {
  429. get { return column_width_internal; }
  430. set { column_width_internal = value; }
  431. }
  432. #endregion Private Properties
  433. #region Public Methods
  434. protected virtual void AddItemsCore (object[] value)
  435. {
  436. Items.AddRange (value);
  437. }
  438. public void BeginUpdate ()
  439. {
  440. suspend_ctrlupdate = true;
  441. }
  442. public void ClearSelected ()
  443. {
  444. foreach (int i in selected_indices) {
  445. UnSelectItem (i, false);
  446. }
  447. selected_indices.ClearIndices ();
  448. selected_items.ClearObjects ();
  449. }
  450. protected virtual ObjectCollection CreateItemCollection ()
  451. {
  452. return new ObjectCollection (this);
  453. }
  454. public void EndUpdate ()
  455. {
  456. suspend_ctrlupdate = false;
  457. UpdateItemInfo (false, -1, -1);
  458. base.Refresh ();
  459. }
  460. public int FindString (String s)
  461. {
  462. return FindString (s, 0);
  463. }
  464. public int FindString (string s, int startIndex)
  465. {
  466. for (int i = startIndex; i < Items.Count; i++) {
  467. if ((Items[i].ToString ()).StartsWith (s))
  468. return i;
  469. }
  470. return -1;
  471. }
  472. public int FindStringExact (string s)
  473. {
  474. return FindStringExact (s, 0);
  475. }
  476. public int FindStringExact (string s, int startIndex)
  477. {
  478. for (int i = startIndex; i < Items.Count; i++) {
  479. if ((Items[i].ToString ()).Equals (s))
  480. return i;
  481. }
  482. return -1;
  483. }
  484. public int GetItemHeight (int index)
  485. {
  486. if (index < 0 || index >= Items.Count)
  487. throw new ArgumentOutOfRangeException ("Index of out range");
  488. if (DrawMode == DrawMode.OwnerDrawVariable && IsHandleCreated == true) {
  489. if ((Items.GetListBoxItem (index)).ItemHeight != -1) {
  490. return (Items.GetListBoxItem (index)).ItemHeight;
  491. }
  492. MeasureItemEventArgs args = new MeasureItemEventArgs (DeviceContext, index, ItemHeight);
  493. OnMeasureItem (args);
  494. (Items.GetListBoxItem (index)).ItemHeight = args.ItemHeight;
  495. return args.ItemHeight;
  496. }
  497. return ItemHeight;
  498. }
  499. public Rectangle GetItemRectangle (int index)
  500. {
  501. if (index < 0 || index >= Items.Count)
  502. throw new ArgumentOutOfRangeException ("GetItemRectangle index out of range.");
  503. Rectangle rect = new Rectangle ();
  504. if (MultiColumn == false) {
  505. rect.X = 0;
  506. rect.Height = GetItemHeight (index);
  507. rect.Width = listbox_info.textdrawing_rect.Width;
  508. if (DrawMode == DrawMode.OwnerDrawVariable) {
  509. rect.Y = 0;
  510. for (int i = 0; i < index; i++) {
  511. rect.Y += GetItemHeight (i);
  512. }
  513. } else {
  514. rect.Y = ItemHeight * index;
  515. }
  516. }
  517. else {
  518. int which_page;
  519. which_page = index / listbox_info.page_size;
  520. rect.Y = (index % listbox_info.page_size) * ItemHeight;
  521. rect.X = which_page * ColumnWidthInternal;
  522. rect.Height = ItemHeight;
  523. rect.Width = ColumnWidthInternal;
  524. }
  525. return rect;
  526. }
  527. public bool GetSelected (int index)
  528. {
  529. if (index < 0 || index >= Items.Count)
  530. throw new ArgumentOutOfRangeException ("Index of out range");
  531. return (Items.GetListBoxItem (index)).Selected;
  532. }
  533. public int IndexFromPoint (Point p)
  534. {
  535. return IndexFromPoint (p.X, p.Y);
  536. }
  537. // Only returns visible points
  538. public int IndexFromPoint (int x, int y)
  539. {
  540. for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
  541. if (GetItemRectangle (i).Contains (x,y) == true)
  542. return i;
  543. }
  544. return -1;
  545. }
  546. protected override void OnChangeUICues (UICuesEventArgs e)
  547. {
  548. base.OnChangeUICues (e);
  549. }
  550. protected override void OnDataSourceChanged (EventArgs e)
  551. {
  552. base.OnDataSourceChanged (e);
  553. }
  554. protected override void OnDisplayMemberChanged (EventArgs e)
  555. {
  556. base.OnDisplayMemberChanged (e);
  557. }
  558. protected virtual void OnDrawItem (DrawItemEventArgs e)
  559. {
  560. Color back_color, fore_color;
  561. if (DrawItem != null && (DrawMode == DrawMode.OwnerDrawFixed || DrawMode == DrawMode.OwnerDrawVariable)) {
  562. DrawItem (this, e);
  563. return;
  564. }
  565. if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
  566. back_color = ThemeEngine.Current.ColorHilight;
  567. fore_color = ThemeEngine.Current.ColorHilightText;
  568. }
  569. else {
  570. back_color = e.BackColor;
  571. fore_color = e.ForeColor;
  572. }
  573. e.Graphics.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush
  574. (back_color), e.Bounds);
  575. e.Graphics.DrawString (Items[e.Index].ToString (), e.Font,
  576. ThemeEngine.Current.ResPool.GetSolidBrush (fore_color),
  577. e.Bounds, string_format);
  578. if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) {
  579. ThemeEngine.Current.CPDrawFocusRectangle (e.Graphics, e.Bounds,
  580. fore_color, back_color);
  581. }
  582. }
  583. protected override void OnFontChanged (EventArgs e)
  584. {
  585. base.OnFontChanged (e);
  586. UpdateShowHorizontalScrollBar ();
  587. UpdateShowVerticalScrollBar ();
  588. RellocateScrollBars ();
  589. CalcClientArea ();
  590. UpdateItemInfo (false, -1, -1);
  591. }
  592. protected override void OnHandleCreated (EventArgs e)
  593. {
  594. base.OnHandleCreated (e);
  595. UpdateInternalClientRect (ClientRectangle);
  596. Controls.Add (vscrollbar_ctrl);
  597. Controls.Add (hscrollbar_ctrl);
  598. UpdateItemInfo (false, -1, -1);
  599. }
  600. protected override void OnHandleDestroyed (EventArgs e)
  601. {
  602. base.OnHandleDestroyed (e);
  603. }
  604. protected virtual void OnMeasureItem (MeasureItemEventArgs e)
  605. {
  606. if (draw_mode != DrawMode.OwnerDrawVariable)
  607. return;
  608. if (MeasureItem != null)
  609. MeasureItem (this, e);
  610. }
  611. protected override void OnParentChanged (EventArgs e)
  612. {
  613. base.OnParentChanged (e);
  614. }
  615. protected override void OnResize (EventArgs e)
  616. {
  617. base.OnResize (e);
  618. UpdateInternalClientRect (ClientRectangle);
  619. }
  620. protected override void OnSelectedIndexChanged (EventArgs e)
  621. {
  622. base.OnSelectedIndexChanged (e);
  623. if (SelectedIndexChanged != null)
  624. SelectedIndexChanged (this, e);
  625. }
  626. protected override void OnSelectedValueChanged (EventArgs e)
  627. {
  628. base.OnSelectedValueChanged (e);
  629. }
  630. public override void Refresh ()
  631. {
  632. if (draw_mode == DrawMode.OwnerDrawVariable) {
  633. for (int i = 0; i < Items.Count; i++) {
  634. (Items.GetListBoxItem (i)).ItemHeight = -1;
  635. }
  636. }
  637. base.Refresh ();
  638. }
  639. protected override void RefreshItem (int index)
  640. {
  641. if (index < 0 || index >= Items.Count)
  642. throw new ArgumentOutOfRangeException ("Index of out range");
  643. if (draw_mode == DrawMode.OwnerDrawVariable) {
  644. (Items.GetListBoxItem (index)).ItemHeight = -1;
  645. }
  646. }
  647. protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
  648. {
  649. base.SetBoundsCore (x, y, width, height, specified);
  650. }
  651. protected override void SetItemCore (int index, object value)
  652. {
  653. if (index < 0 || index >= Items.Count)
  654. return;
  655. Items[index] = value;
  656. }
  657. protected override void SetItemsCore (IList value)
  658. {
  659. }
  660. public void SetSelected (int index, bool value)
  661. {
  662. if (index < 0 || index >= Items.Count)
  663. throw new ArgumentOutOfRangeException ("Index of out range");
  664. if (SelectionMode == SelectionMode.None)
  665. throw new InvalidOperationException ();
  666. if (value)
  667. SelectItem (index);
  668. else
  669. UnSelectItem (index, true);
  670. }
  671. protected virtual void Sort ()
  672. {
  673. if (Items.Count == 0)
  674. return;
  675. Items.Sort ();
  676. base.Refresh ();
  677. }
  678. public override string ToString ()
  679. {
  680. return base.ToString () + ", Items Count: " + Items.Count;
  681. }
  682. protected virtual void WmReflectCommand (ref Message m)
  683. {
  684. }
  685. protected override void WndProc (ref Message m)
  686. {
  687. switch ((Msg) m.Msg) {
  688. case Msg.WM_PAINT: {
  689. PaintEventArgs paint_event;
  690. paint_event = XplatUI.PaintEventStart (Handle);
  691. OnPaintLB (paint_event);
  692. XplatUI.PaintEventEnd (Handle);
  693. return;
  694. }
  695. case Msg.WM_ERASEBKGND:
  696. m.Result = (IntPtr) 1;
  697. return;
  698. default:
  699. break;
  700. }
  701. base.WndProc (ref m);
  702. }
  703. #endregion Public Methods
  704. #region Private Methods
  705. internal void CalcClientArea ()
  706. {
  707. listbox_info.textdrawing_rect = listbox_info.client_rect;
  708. listbox_info.textdrawing_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
  709. listbox_info.textdrawing_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
  710. //BUG: Top and Left decorations
  711. listbox_info.textdrawing_rect.Height -= ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle);
  712. listbox_info.textdrawing_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
  713. if (listbox_info.show_verticalsb)
  714. listbox_info.textdrawing_rect.Width -= vscrollbar_ctrl.Width;
  715. if (listbox_info.show_horizontalsb)
  716. listbox_info.textdrawing_rect.Height -= hscrollbar_ctrl.Height;
  717. if (DrawMode == DrawMode.OwnerDrawVariable) {
  718. int height = 0;
  719. listbox_info.page_size = 0;
  720. for (int i = 0; i < Items.Count; i++) {
  721. height += GetItemHeight (i);
  722. if (height > listbox_info.textdrawing_rect.Height)
  723. break;
  724. listbox_info.page_size++;
  725. }
  726. } else {
  727. listbox_info.page_size = listbox_info.textdrawing_rect.Height / listbox_info.item_height;
  728. }
  729. if (listbox_info.page_size == 0) {
  730. listbox_info.page_size = 1;
  731. }
  732. /* Adjust size to visible the maxim number of displayable items */
  733. if (IntegralHeight == true) {
  734. // From MS Docs: The integral height is based on the height of the ListBox, rather than
  735. // the client area height. As a result, when the IntegralHeight property is set true,
  736. // items can still be partially shown if scroll bars are displayed.
  737. int remaining = (listbox_info.client_rect.Height -
  738. ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle) -
  739. ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle)) %
  740. listbox_info.item_height;
  741. if (remaining > 0) {
  742. listbox_info.client_rect.Height -= remaining;
  743. CalcClientArea ();
  744. RellocateScrollBars ();
  745. base.Refresh ();
  746. }
  747. }
  748. }
  749. internal void Draw (Rectangle clip)
  750. {
  751. if (LBoxInfo.textdrawing_rect.Contains (clip) == false) {
  752. // IntegralHeight has effect, we also have to paint the unused area
  753. if (ClientRectangle.Height > listbox_info.client_rect.Height) {
  754. Region area = new Region (ClientRectangle);
  755. area.Exclude (listbox_info.client_rect);
  756. DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (Parent.BackColor),
  757. area.GetBounds (DeviceContext));
  758. }
  759. DeviceContext.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), LBoxInfo.textdrawing_rect);
  760. }
  761. if (Items.Count > 0) {
  762. Rectangle item_rect;
  763. DrawItemState state = DrawItemState.None;
  764. for (int i = LBoxInfo.top_item; i <= LBoxInfo.last_item; i++) {
  765. item_rect = GetItemDisplayRectangle (i, LBoxInfo.top_item);
  766. if (clip.IntersectsWith (item_rect) == false)
  767. continue;
  768. /* Draw item */
  769. state = DrawItemState.None;
  770. if ((Items.GetListBoxItem (i)).Selected) {
  771. state |= DrawItemState.Selected;
  772. }
  773. if (has_focus == true && focused_item == i)
  774. state |= DrawItemState.Focus;
  775. OnDrawItem (new DrawItemEventArgs (DeviceContext, Font, item_rect,
  776. i, state, ForeColor, BackColor));
  777. }
  778. }
  779. ThemeEngine.Current.DrawListBoxDecorations (DeviceContext, this);
  780. }
  781. // Converts a GetItemRectangle to a one that we can display
  782. internal Rectangle GetItemDisplayRectangle (int index, int first_displayble)
  783. {
  784. Rectangle item_rect;
  785. Rectangle first_item_rect = GetItemRectangle (first_displayble);
  786. item_rect = GetItemRectangle (index);
  787. item_rect.X -= first_item_rect.X;
  788. item_rect.Y -= first_item_rect.Y;
  789. item_rect.Y += ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle);
  790. item_rect.X += ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle);
  791. item_rect.Width -= ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle);
  792. return item_rect;
  793. }
  794. // Value Changed
  795. private void HorizontalScrollEvent (object sender, EventArgs e)
  796. {
  797. LBoxInfo.top_item = listbox_info.page_size * hscrollbar_ctrl.Value;
  798. LBoxInfo.last_item = LastVisibleItem ();
  799. base.Refresh ();
  800. }
  801. // Only returns visible points. The diference of with IndexFromPoint is that the rectangle
  802. // has screen coordinates
  803. internal int IndexFromPointDisplayRectangle (int x, int y)
  804. {
  805. for (int i = LBoxInfo.top_item; i < LBoxInfo.last_item; i++) {
  806. if (GetItemDisplayRectangle (i, LBoxInfo.top_item).Contains (x, y) == true)
  807. return i;
  808. }
  809. return -1;
  810. }
  811. private int LastVisibleItem ()
  812. {
  813. Rectangle item_rect;
  814. int top_y = LBoxInfo.textdrawing_rect.Y + LBoxInfo.textdrawing_rect.Height;
  815. int i = 0;
  816. if (LBoxInfo.top_item >= Items.Count)
  817. return LBoxInfo.top_item;
  818. for (i = LBoxInfo.top_item; i < Items.Count; i++) {
  819. item_rect = GetItemDisplayRectangle (i, LBoxInfo.top_item);
  820. if (MultiColumn) {
  821. if (item_rect.X > LBoxInfo.textdrawing_rect.Width)
  822. return i - 1;
  823. }
  824. else {
  825. if (IntegralHeight) {
  826. if (item_rect.Y + item_rect.Height > top_y) {
  827. return i - 1;
  828. }
  829. }
  830. else {
  831. if (item_rect.Y + item_rect.Height > top_y)
  832. return i - 1;
  833. }
  834. }
  835. }
  836. return i - 1;
  837. }
  838. private void UpdatedTopItem ()
  839. {
  840. if (multicolumn) {
  841. int col = (LBoxInfo.top_item / LBoxInfo.page_size);
  842. hscrollbar_ctrl.Value = col;
  843. }
  844. else {
  845. if (LBoxInfo.top_item > vscrollbar_ctrl.Maximum)
  846. vscrollbar_ctrl.Value = vscrollbar_ctrl.Maximum;
  847. else
  848. vscrollbar_ctrl.Value = LBoxInfo.top_item;
  849. }
  850. }
  851. // Navigates to the indicated item and returns the new item
  852. private int NavigateItemVisually (ItemNavigation navigation)
  853. {
  854. int page_size, columns, selected_index = -1;
  855. if (multicolumn) {
  856. columns = LBoxInfo.textdrawing_rect.Width / ColumnWidthInternal;
  857. page_size = columns * LBoxInfo.page_size;
  858. if (page_size == 0) {
  859. page_size = LBoxInfo.page_size;
  860. }
  861. } else {
  862. page_size = LBoxInfo.page_size;
  863. }
  864. switch (navigation) {
  865. case ItemNavigation.PreviousColumn: {
  866. if (focused_item - LBoxInfo.page_size < 0) {
  867. return -1;
  868. }
  869. if (focused_item - LBoxInfo.page_size < LBoxInfo.top_item) {
  870. LBoxInfo.top_item = focused_item - LBoxInfo.page_size;
  871. UpdatedTopItem ();
  872. }
  873. selected_index = focused_item - LBoxInfo.page_size;
  874. break;
  875. }
  876. case ItemNavigation.NextColumn: {
  877. if (focused_item + LBoxInfo.page_size >= Items.Count) {
  878. break;
  879. }
  880. if (focused_item + LBoxInfo.page_size > LBoxInfo.last_item) {
  881. LBoxInfo.top_item = focused_item;
  882. UpdatedTopItem ();
  883. }
  884. selected_index = focused_item + LBoxInfo.page_size;
  885. break;
  886. }
  887. case ItemNavigation.First: {
  888. LBoxInfo.top_item = 0;
  889. selected_index = 0;
  890. UpdatedTopItem ();
  891. break;
  892. }
  893. case ItemNavigation.Last: {
  894. if (Items.Count < LBoxInfo.page_size) {
  895. LBoxInfo.top_item = 0;
  896. selected_index = Items.Count - 1;
  897. UpdatedTopItem ();
  898. } else {
  899. LBoxInfo.top_item = Items.Count - LBoxInfo.page_size;
  900. selected_index = Items.Count - 1;
  901. UpdatedTopItem ();
  902. }
  903. break;
  904. }
  905. case ItemNavigation.Next: {
  906. if (focused_item + 1 < Items.Count) {
  907. if (focused_item + 1 > LBoxInfo.last_item) {
  908. LBoxInfo.top_item++;
  909. UpdatedTopItem ();
  910. }
  911. selected_index = focused_item + 1;
  912. }
  913. break;
  914. }
  915. case ItemNavigation.Previous: {
  916. if (focused_item > 0) {
  917. if (focused_item - 1 < LBoxInfo.top_item) {
  918. LBoxInfo.top_item--;
  919. UpdatedTopItem ();
  920. }
  921. selected_index = focused_item - 1;
  922. }
  923. break;
  924. }
  925. case ItemNavigation.NextPage: {
  926. if (Items.Count < page_size) {
  927. NavigateItemVisually (ItemNavigation.Last);
  928. break;
  929. }
  930. if (focused_item + page_size - 1 >= Items.Count) {
  931. LBoxInfo.top_item = Items.Count - page_size;
  932. UpdatedTopItem ();
  933. selected_index = Items.Count - 1;
  934. }
  935. else {
  936. if (focused_item + page_size - 1 > LBoxInfo.last_item) {
  937. LBoxInfo.top_item = focused_item;
  938. UpdatedTopItem ();
  939. }
  940. selected_index = focused_item + page_size - 1;
  941. }
  942. break;
  943. }
  944. case ItemNavigation.PreviousPage: {
  945. if (focused_item - (LBoxInfo.page_size - 1) <= 0) {
  946. LBoxInfo.top_item = 0;
  947. vscrollbar_ctrl.Value = LBoxInfo.top_item;
  948. SelectedIndex = 0;
  949. }
  950. else {
  951. if (focused_item - (LBoxInfo.page_size - 1) < LBoxInfo.top_item) {
  952. LBoxInfo.top_item = focused_item - (LBoxInfo.page_size - 1);
  953. vscrollbar_ctrl.Value = LBoxInfo.top_item;
  954. }
  955. selected_index = focused_item - (LBoxInfo.page_size - 1);
  956. }
  957. break;
  958. }
  959. default:
  960. break;
  961. }
  962. return selected_index;
  963. }
  964. private void OnGotFocus (object sender, EventArgs e)
  965. {
  966. has_focus = true;
  967. if (focused_item != -1) {
  968. Rectangle invalidate = GetItemDisplayRectangle (focused_item, LBoxInfo.top_item);
  969. Invalidate (invalidate);
  970. }
  971. }
  972. private void OnLostFocus (object sender, EventArgs e)
  973. {
  974. has_focus = false;
  975. if (focused_item != -1) {
  976. Rectangle invalidate = GetItemDisplayRectangle (focused_item, LBoxInfo.top_item);
  977. Invalidate (invalidate);
  978. }
  979. }
  980. private void OnKeyDownLB (object sender, KeyEventArgs e)
  981. {
  982. int new_item = -1;
  983. switch (e.KeyCode) {
  984. case Keys.ControlKey:
  985. ctrl_pressed = true;
  986. break;
  987. case Keys.ShiftKey:
  988. shift_pressed = true;
  989. break;
  990. case Keys.Home:
  991. new_item = NavigateItemVisually (ItemNavigation.First);
  992. break;
  993. case Keys.End:
  994. new_item = NavigateItemVisually (ItemNavigation.Last);
  995. break;
  996. case Keys.Up:
  997. new_item = NavigateItemVisually (ItemNavigation.Previous);
  998. break;
  999. case Keys.Down:
  1000. new_item = NavigateItemVisually (ItemNavigation.Next);
  1001. break;
  1002. case Keys.PageUp:
  1003. new_item = NavigateItemVisually (ItemNavigation.PreviousPage);
  1004. break;
  1005. case Keys.PageDown:
  1006. new_item = NavigateItemVisually (ItemNavigation.NextPage);
  1007. break;
  1008. case Keys.Right:
  1009. if (multicolumn == true) {
  1010. new_item = NavigateItemVisually (ItemNavigation.NextColumn);
  1011. }
  1012. break;
  1013. case Keys.Left:
  1014. if (multicolumn == true) {
  1015. new_item = NavigateItemVisually (ItemNavigation.PreviousColumn);
  1016. }
  1017. break;
  1018. case Keys.Space:
  1019. if (selection_mode == SelectionMode.MultiSimple) {
  1020. SelectedItemFromNavigation (focused_item);
  1021. }
  1022. break;
  1023. default:
  1024. break;
  1025. }
  1026. if (new_item != -1) {
  1027. SetFocusedItem (new_item);
  1028. }
  1029. if (new_item != -1) {
  1030. if (selection_mode != SelectionMode.MultiSimple && selection_mode != SelectionMode.None) {
  1031. SelectedItemFromNavigation (new_item);
  1032. }
  1033. }
  1034. }
  1035. private void OnKeyUpLB (object sender, KeyEventArgs e)
  1036. {
  1037. switch (e.KeyCode) {
  1038. case Keys.ControlKey:
  1039. ctrl_pressed = false;
  1040. break;
  1041. case Keys.ShiftKey:
  1042. shift_pressed = false;
  1043. break;
  1044. default:
  1045. break;
  1046. }
  1047. }
  1048. internal virtual void OnMouseDownLB (object sender, MouseEventArgs e)
  1049. {
  1050. int index = IndexFromPointDisplayRectangle (e.X, e.Y);
  1051. if (index != -1) {
  1052. SelectedItemFromNavigation (index);
  1053. SetFocusedItem (index);
  1054. }
  1055. }
  1056. private void OnPaintLB (PaintEventArgs pevent)
  1057. {
  1058. if (Width <= 0 || Height <= 0 || Visible == false || suspend_ctrlupdate == true)
  1059. return;
  1060. /* Copies memory drawing buffer to screen*/
  1061. Draw (pevent.ClipRectangle);
  1062. pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
  1063. if (Paint != null)
  1064. Paint (this, pevent);
  1065. }
  1066. internal void RellocateScrollBars ()
  1067. {
  1068. if (listbox_info.show_verticalsb) {
  1069. vscrollbar_ctrl.Size = new Size (vscrollbar_ctrl.Width,
  1070. listbox_info.client_rect.Height - ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle) -
  1071. ThemeEngine.Current.DrawListBoxDecorationBottom (BorderStyle));
  1072. vscrollbar_ctrl.Location = new Point (listbox_info.client_rect.Width - vscrollbar_ctrl.Width
  1073. - ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle),
  1074. ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle));
  1075. }
  1076. if (listbox_info.show_horizontalsb) {
  1077. int width;
  1078. width = listbox_info.client_rect.Width - (ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle) + ThemeEngine.Current.DrawListBoxDecorationRight (BorderStyle));
  1079. if (listbox_info.show_verticalsb)
  1080. width -= vscrollbar_ctrl.Width;
  1081. hscrollbar_ctrl.Size = new Size (width, hscrollbar_ctrl.Height);
  1082. hscrollbar_ctrl.Location = new Point (ThemeEngine.Current.DrawListBoxDecorationLeft (BorderStyle),
  1083. listbox_info.client_rect.Height - hscrollbar_ctrl.Height
  1084. - ThemeEngine.Current.DrawListBoxDecorationTop (BorderStyle));
  1085. }
  1086. CalcClientArea ();
  1087. }
  1088. // Add an item in the Selection array and marks it visually as selected
  1089. private void SelectItem (int index)
  1090. {
  1091. if (index == -1)
  1092. return;
  1093. Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
  1094. (Items.GetListBoxItem (index)).Selected = true;
  1095. selected_indices.AddIndex (index);
  1096. selected_items.AddObject (Items[index]);
  1097. if (ClientRectangle.Contains (invalidate))
  1098. Invalidate (invalidate);
  1099. }
  1100. // An item navigation operation (mouse or keyboard) has caused to select a new item
  1101. private void SelectedItemFromNavigation (int index)
  1102. {
  1103. switch (SelectionMode) {
  1104. case SelectionMode.None: // Do nothing
  1105. break;
  1106. case SelectionMode.One: {
  1107. SelectedIndex = index;
  1108. break;
  1109. }
  1110. case SelectionMode.MultiSimple: {
  1111. if (selected_index == -1) {
  1112. SelectedIndex = index;
  1113. } else {
  1114. if ((Items.GetListBoxItem (index)).Selected) // BUG: index or selected_index?
  1115. UnSelectItem (index, true);
  1116. else {
  1117. SelectItem (index);
  1118. OnSelectedIndexChanged (new EventArgs ());
  1119. }
  1120. }
  1121. break;
  1122. }
  1123. case SelectionMode.MultiExtended: {
  1124. if (selected_index == -1) {
  1125. SelectedIndex = index;
  1126. } else {
  1127. if (ctrl_pressed == false && shift_pressed == false) {
  1128. ClearSelected ();
  1129. }
  1130. if (shift_pressed == true) {
  1131. ShiftSelection (index);
  1132. } else { // ctrl_pressed or single item
  1133. SelectItem (index);
  1134. }
  1135. OnSelectedIndexChanged (new EventArgs ());
  1136. }
  1137. break;
  1138. }
  1139. default:
  1140. break;
  1141. }
  1142. }
  1143. private void ShiftSelection (int index)
  1144. {
  1145. int shorter_item = -1, dist = Items.Count + 1, cur_dist;
  1146. foreach (int idx in selected_indices) {
  1147. if (idx > index) {
  1148. cur_dist = idx - index;
  1149. }
  1150. else {
  1151. cur_dist = index - idx;
  1152. }
  1153. if (cur_dist < dist) {
  1154. dist = cur_dist;
  1155. shorter_item = idx;
  1156. }
  1157. }
  1158. if (shorter_item != -1) {
  1159. int start, end;
  1160. if (shorter_item > index) {
  1161. start = index;
  1162. end = shorter_item;
  1163. } else {
  1164. start = shorter_item;
  1165. end = index;
  1166. }
  1167. ClearSelected ();
  1168. for (int idx = start; idx <= end; idx++) {
  1169. SelectItem (idx);
  1170. }
  1171. }
  1172. }
  1173. void SetFocusedItem (int index)
  1174. {
  1175. Rectangle invalidate;
  1176. int prev = focused_item;
  1177. focused_item = index;
  1178. if (has_focus == false)
  1179. return;
  1180. if (prev != -1) { // Invalidates previous item
  1181. invalidate = GetItemDisplayRectangle (prev, LBoxInfo.top_item);
  1182. Invalidate (invalidate);
  1183. }
  1184. if (index != -1) {
  1185. invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
  1186. Invalidate (invalidate);
  1187. }
  1188. }
  1189. // Removes an item in the Selection array and marks it visually as unselected
  1190. private void UnSelectItem (int index, bool remove)
  1191. {
  1192. if (index == -1)
  1193. return;
  1194. Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
  1195. (Items.GetListBoxItem (index)).Selected = false;
  1196. if (remove) {
  1197. selected_indices.RemoveIndex (index);
  1198. selected_items.RemoveObject (Items[index]);
  1199. }
  1200. if (ClientRectangle.Contains (invalidate))
  1201. Invalidate (invalidate);
  1202. }
  1203. private void UpdateFormatString ()
  1204. {
  1205. Console.WriteLine ("UpdateFormatString {0}", RightToLeft);
  1206. if (RightToLeft == RightToLeft.Yes)
  1207. string_format.Alignment = StringAlignment.Far;
  1208. else
  1209. string_format.Alignment = StringAlignment.Near;
  1210. if (UseTabStops)
  1211. string_format.SetTabStops (0, new float [] {(float)(Font.Height * 3.7)});
  1212. }
  1213. // Updates the scrollbar's position with the new items and inside area
  1214. internal virtual void UpdateItemInfo (bool adding, int first, int last)
  1215. {
  1216. if (!IsHandleCreated || suspend_ctrlupdate == true)
  1217. return;
  1218. UpdateShowVerticalScrollBar ();
  1219. if (listbox_info.show_verticalsb && Items.Count > listbox_info.page_size)
  1220. if (vscrollbar_ctrl.Enabled)
  1221. vscrollbar_ctrl.Maximum = Items.Count - listbox_info.page_size;
  1222. if (listbox_info.show_horizontalsb) {
  1223. if (MultiColumn) {
  1224. int fullpage = (listbox_info.page_size * (listbox_info.client_rect.Width / ColumnWidthInternal));
  1225. if (hscrollbar_ctrl.Enabled && listbox_info.page_size > 0)
  1226. hscrollbar_ctrl.Maximum = Math.Max (0, 1 + ((Items.Count - fullpage) / listbox_info.page_size));
  1227. }
  1228. }
  1229. if (MultiColumn == false) {
  1230. /* Calc the longest items for non multicolumn listboxes */
  1231. if ((first == -1 && last == -1) || (adding == false)) {
  1232. SizeF size;
  1233. for (int i = 0; i < Items.Count; i++) {
  1234. size = DeviceContext.MeasureString (Items[i].ToString(), Font);
  1235. if ((int) size.Width > listbox_info.max_itemwidth)
  1236. listbox_info.max_itemwidth = (int) size.Width;
  1237. }
  1238. }
  1239. else {
  1240. if (adding) {
  1241. SizeF size;
  1242. for (int i = first; i < last + 1; i++) {
  1243. size = DeviceContext.MeasureString (Items[i].ToString(), Font);
  1244. if ((int) size.Width > listbox_info.max_itemwidth)
  1245. listbox_info.max_itemwidth = (int) size.Width;
  1246. }
  1247. }
  1248. }
  1249. }
  1250. if (sorted)
  1251. Sort ();
  1252. SelectedItems.ReCreate ();
  1253. SelectedIndices.ReCreate ();
  1254. LBoxInfo.last_item = LastVisibleItem ();
  1255. UpdateShowHorizontalScrollBar ();
  1256. base.Refresh ();
  1257. }
  1258. private void UpdateInternalClientRect (Rectangle client_rectangle)
  1259. {
  1260. listbox_info.client_rect = client_rectangle;
  1261. UpdateShowHorizontalScrollBar ();
  1262. UpdateShowVerticalScrollBar ();
  1263. RellocateScrollBars ();
  1264. UpdateItemInfo (false, -1, -1);
  1265. }
  1266. /* Determines if the horizontal scrollbar has to be displyed */
  1267. private void UpdateShowHorizontalScrollBar ()
  1268. {
  1269. bool show = false;
  1270. bool enabled = true;
  1271. if (MultiColumn) { /* Horizontal scrollbar is always shown in Multicolum mode */
  1272. /* Is it really need it */
  1273. int page_size = listbox_info.client_rect.Height / listbox_info.item_height;
  1274. int fullpage = (page_size * (listbox_info.textdrawing_rect.Height / ColumnWidthInternal));
  1275. if (Items.Count > fullpage) {
  1276. if (IntegralHeight == false)
  1277. show = true;
  1278. }
  1279. else { /* Acording to MS Documentation ScrollAlwaysVisible only affects Horizontal scrollbars but
  1280. this is not true for MultiColumn listboxes */
  1281. if (ScrollAlwaysVisible == true) {
  1282. enabled = false;
  1283. show = true;
  1284. }
  1285. }
  1286. } else { /* If large item*/
  1287. if (listbox_info.max_itemwidth > listbox_info.client_rect.Width && HorizontalScrollbar) {
  1288. show = true;
  1289. hscrollbar_ctrl.Maximum = listbox_info.max_itemwidth;
  1290. }
  1291. }
  1292. if (hscrollbar_ctrl.Enabled != enabled)
  1293. hscrollbar_ctrl.Enabled = enabled;
  1294. if (listbox_info.show_horizontalsb == show)
  1295. return;
  1296. listbox_info.show_horizontalsb = show;
  1297. hscrollbar_ctrl.Visible = show;
  1298. if (show == true) {
  1299. RellocateScrollBars ();
  1300. }
  1301. CalcClientArea ();
  1302. }
  1303. /* Determines if the vertical scrollbar has to be displyed */
  1304. private void UpdateShowVerticalScrollBar ()
  1305. {
  1306. bool show = false;
  1307. bool enabled = true;
  1308. if (!MultiColumn) { /* Vertical scrollbar is never shown in Multicolum mode */
  1309. if (Items.Count > listbox_info.page_size) {
  1310. show = true;
  1311. }
  1312. else
  1313. if (ScrollAlwaysVisible) {
  1314. show = true;
  1315. enabled = false;
  1316. }
  1317. }
  1318. if (vscrollbar_ctrl.Enabled != enabled)
  1319. vscrollbar_ctrl.Enabled = enabled;
  1320. if (listbox_info.show_verticalsb == show)
  1321. return;
  1322. listbox_info.show_verticalsb = show;
  1323. vscrollbar_ctrl.Visible = show;
  1324. if (show == true) {
  1325. if (vscrollbar_ctrl.Enabled)
  1326. vscrollbar_ctrl.Maximum = Items.Count - listbox_info.page_size;
  1327. RellocateScrollBars ();
  1328. }
  1329. CalcClientArea ();
  1330. }
  1331. // Value Changed
  1332. private void VerticalScrollEvent (object sender, EventArgs e)
  1333. {
  1334. LBoxInfo.top_item = /*listbox_info.page_size + */ vscrollbar_ctrl.Value;
  1335. LBoxInfo.last_item = LastVisibleItem ();
  1336. base.Refresh ();
  1337. }
  1338. #endregion Private Methods
  1339. /*
  1340. ListBox.ObjectCollection
  1341. */
  1342. public class ObjectCollection : IList, ICollection, IEnumerable
  1343. {
  1344. // Compare objects
  1345. internal class ListObjectComparer : IComparer
  1346. {
  1347. private ListBox owner;
  1348. public ListObjectComparer (ListBox owner)
  1349. {
  1350. this.owner = owner;
  1351. }
  1352. public int Compare (object a, object b)
  1353. {
  1354. string str1 = a.ToString ();
  1355. string str2 = b.ToString ();
  1356. return str1.CompareTo (str2);
  1357. }
  1358. }
  1359. // Compare ListItem
  1360. internal class ListItemComparer : IComparer
  1361. {
  1362. private ListBox owner;
  1363. public ListItemComparer (ListBox owner)
  1364. {
  1365. this.owner = owner;
  1366. }
  1367. public int Compare (object a, object b)
  1368. {
  1369. int index1 = ((ListBox.ListBoxItem) (a)).Index;
  1370. int index2 = ((ListBox.ListBoxItem) (b)).Index;
  1371. string str1 = owner.Items[index1].ToString ();
  1372. string str2 = owner.Items[index2].ToString ();
  1373. return str1.CompareTo (str2);
  1374. }
  1375. }
  1376. private ListBox owner;
  1377. internal ArrayList object_items = new ArrayList ();
  1378. internal ArrayList listbox_items = new ArrayList ();
  1379. public ObjectCollection (ListBox owner)
  1380. {
  1381. this.owner = owner;
  1382. }
  1383. public ObjectCollection (ListBox owner, object[] obj)
  1384. {
  1385. this.owner = owner;
  1386. AddRange (obj);
  1387. }
  1388. public ObjectCollection (ListBox owner, ObjectCollection obj)
  1389. {
  1390. this.owner = owner;
  1391. AddRange (obj);
  1392. }
  1393. #region Public Properties
  1394. public virtual int Count {
  1395. get { return object_items.Count; }
  1396. }
  1397. public virtual bool IsReadOnly {
  1398. get { return false; }
  1399. }
  1400. public virtual object this [int index] {
  1401. get {
  1402. if (index < 0 || index >= Count)
  1403. throw new ArgumentOutOfRangeException ("Index of out range");
  1404. return object_items[index];
  1405. }
  1406. set {
  1407. if (index < 0 || index >= Count)
  1408. throw new ArgumentOutOfRangeException ("Index of out range");
  1409. object_items[index] = value;
  1410. }
  1411. }
  1412. bool ICollection.IsSynchronized {
  1413. get { return false; }
  1414. }
  1415. object ICollection.SyncRoot {
  1416. get { return this; }
  1417. }
  1418. bool IList.IsFixedSize {
  1419. get { return false; }
  1420. }
  1421. #endregion Public Properties
  1422. #region Public Methods
  1423. public int Add (object item)
  1424. {
  1425. int idx;
  1426. idx = AddItem (item);
  1427. owner.UpdateItemInfo (true, idx, idx);
  1428. return idx;
  1429. }
  1430. public void AddRange (object[] items)
  1431. {
  1432. int cnt = Count;
  1433. foreach (object mi in items)
  1434. AddItem (mi);
  1435. owner.UpdateItemInfo (true, cnt, Count);
  1436. }
  1437. public void AddRange (ObjectCollection col)
  1438. {
  1439. int cnt = Count;
  1440. foreach (object mi in col)
  1441. AddItem (mi);
  1442. owner.UpdateItemInfo (true, cnt, Count);
  1443. }
  1444. public virtual void Clear ()
  1445. {
  1446. object_items.Clear ();
  1447. listbox_items.Clear ();
  1448. owner.UpdateItemInfo (false, -1, -1);
  1449. }
  1450. public virtual bool Contains (object obj)
  1451. {
  1452. return object_items.Contains (obj);
  1453. }
  1454. public void CopyTo (object[] dest, int arrayIndex)
  1455. {
  1456. object_items.CopyTo (dest, arrayIndex);
  1457. }
  1458. void ICollection.CopyTo (Array dest, int index)
  1459. {
  1460. object_items.CopyTo (dest, index);
  1461. }
  1462. public virtual IEnumerator GetEnumerator ()
  1463. {
  1464. return object_items.GetEnumerator ();
  1465. }
  1466. int IList.Add (object item)
  1467. {
  1468. return Add (item);
  1469. }
  1470. public virtual int IndexOf (object value)
  1471. {
  1472. return object_items.IndexOf (value);
  1473. }
  1474. public virtual void Insert (int index, object item)
  1475. {
  1476. throw new NotImplementedException ();
  1477. }
  1478. public virtual void Remove (object value)
  1479. {
  1480. RemoveAt (IndexOf (value));
  1481. owner.UpdateItemInfo (false, -1, -1);
  1482. }
  1483. public virtual void RemoveAt (int index)
  1484. {
  1485. if (index < 0 || index >= Count)
  1486. throw new ArgumentOutOfRangeException ("Index of out range");
  1487. object_items.RemoveAt (index);
  1488. listbox_items.RemoveAt (index);
  1489. owner.UpdateItemInfo (false, -1, -1);
  1490. }
  1491. #endregion Public Methods
  1492. #region Private Methods
  1493. private int AddItem (object item)
  1494. {
  1495. int cnt = object_items.Count;
  1496. object_items.Add (item);
  1497. listbox_items.Add (new ListBox.ListBoxItem (cnt));
  1498. return cnt;
  1499. }
  1500. internal ListBox.ListBoxItem GetListBoxItem (int index)
  1501. {
  1502. if (index < 0 || index >= Count)
  1503. throw new ArgumentOutOfRangeException ("Index of out range");
  1504. return (ListBox.ListBoxItem) listbox_items[index];
  1505. }
  1506. internal void SetListBoxItem (ListBox.ListBoxItem item, int index)
  1507. {
  1508. if (index < 0 || index >= Count)
  1509. throw new ArgumentOutOfRangeException ("Index of out range");
  1510. listbox_items[index] = item;
  1511. }
  1512. internal void Sort ()
  1513. {
  1514. /* Keep this order */
  1515. listbox_items.Sort (new ListItemComparer (owner));
  1516. object_items.Sort (new ListObjectComparer (owner));
  1517. for (int i = 0; i < listbox_items.Count; i++) {
  1518. ListBox.ListBoxItem item = GetListBoxItem (i);
  1519. item.Index = i;
  1520. }
  1521. }
  1522. #endregion Private Methods
  1523. }
  1524. /*
  1525. ListBox.SelectedIndexCollection
  1526. */
  1527. public class SelectedIndexCollection : IList, ICollection, IEnumerable
  1528. {
  1529. private ListBox owner;
  1530. private ArrayList indices = new ArrayList ();
  1531. public SelectedIndexCollection (ListBox owner)
  1532. {
  1533. this.owner = owner;
  1534. }
  1535. #region Public Properties
  1536. public virtual int Count {
  1537. get { return indices.Count; }
  1538. }
  1539. public virtual bool IsReadOnly {
  1540. get { return true; }
  1541. }
  1542. public int this [int index] {
  1543. get {
  1544. if (index < 0 || index >= Count)
  1545. throw new ArgumentOutOfRangeException ("Index of out range");
  1546. return (int) indices[index];
  1547. }
  1548. }
  1549. bool ICollection.IsSynchronized {
  1550. get { return true; }
  1551. }
  1552. bool IList.IsFixedSize{
  1553. get { return true; }
  1554. }
  1555. object ICollection.SyncRoot {
  1556. get { return this; }
  1557. }
  1558. #endregion Public Properties
  1559. #region Public Methods
  1560. public bool Contains (int selectedIndex)
  1561. {
  1562. return indices.Contains (selectedIndex);
  1563. }
  1564. public virtual void CopyTo (Array dest, int index)
  1565. {
  1566. indices.CopyTo (dest, index);
  1567. }
  1568. public virtual IEnumerator GetEnumerator ()
  1569. {
  1570. return indices.GetEnumerator ();
  1571. }
  1572. int IList.Add (object obj)
  1573. {
  1574. throw new NotSupportedException ();
  1575. }
  1576. void IList.Clear ()
  1577. {
  1578. throw new NotSupportedException ();
  1579. }
  1580. bool IList.Contains (object selectedIndex)
  1581. {
  1582. return Contains ((int)selectedIndex);
  1583. }
  1584. int IList.IndexOf (object selectedIndex)
  1585. {
  1586. return IndexOf ((int) selectedIndex);
  1587. }
  1588. void IList.Insert (int index, object value)
  1589. {
  1590. throw new NotSupportedException ();
  1591. }
  1592. void IList.Remove (object value)
  1593. {
  1594. throw new NotSupportedException ();
  1595. }
  1596. void IList.RemoveAt (int index)
  1597. {
  1598. throw new NotSupportedException ();
  1599. }
  1600. object IList.this[int index]{
  1601. get {return indices[index]; }
  1602. set {throw new NotImplementedException (); }
  1603. }
  1604. public int IndexOf (int selectedIndex)
  1605. {
  1606. return indices.IndexOf (selectedIndex);
  1607. }
  1608. #endregion Public Methods
  1609. #region Private Methods
  1610. internal void AddIndex (int index)
  1611. {
  1612. indices.Add (index);
  1613. }
  1614. internal void ClearIndices ()
  1615. {
  1616. indices.Clear ();
  1617. }
  1618. internal void RemoveIndex (int index)
  1619. {
  1620. indices.Remove (index);
  1621. }
  1622. internal void ReCreate ()
  1623. {
  1624. indices.Clear ();
  1625. for (int i = 0; i < owner.Items.Count; i++) {
  1626. ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
  1627. if (item.Selected)
  1628. indices.Add (item.Index);
  1629. }
  1630. }
  1631. #endregion Private Methods
  1632. }
  1633. /*
  1634. SelectedObjectCollection
  1635. */
  1636. public class SelectedObjectCollection : IList, ICollection, IEnumerable
  1637. {
  1638. private ListBox owner;
  1639. private ArrayList object_items = new ArrayList ();
  1640. public SelectedObjectCollection (ListBox owner)
  1641. {
  1642. this.owner = owner;
  1643. }
  1644. #region Public Properties
  1645. public virtual int Count {
  1646. get { return object_items.Count; }
  1647. }
  1648. public virtual bool IsReadOnly {
  1649. get { return true; }
  1650. }
  1651. public virtual object this [int index] {
  1652. get {
  1653. if (index < 0 || index >= Count)
  1654. throw new ArgumentOutOfRangeException ("Index of out range");
  1655. return object_items[index];
  1656. }
  1657. set {throw new NotSupportedException ();}
  1658. }
  1659. bool ICollection.IsSynchronized {
  1660. get { return true; }
  1661. }
  1662. object ICollection.SyncRoot {
  1663. get { return this; }
  1664. }
  1665. bool IList.IsFixedSize {
  1666. get { return true; }
  1667. }
  1668. object IList.this[int index] {
  1669. get { return object_items[index]; }
  1670. set { throw new NotSupportedException (); }
  1671. }
  1672. #endregion Public Properties
  1673. #region Public Methods
  1674. public virtual bool Contains (object selectedObject)
  1675. {
  1676. return object_items.Contains (selectedObject);
  1677. }
  1678. public virtual void CopyTo (Array dest, int index)
  1679. {
  1680. object_items.CopyTo (dest, index);
  1681. }
  1682. int IList.Add (object value)
  1683. {
  1684. throw new NotSupportedException ();
  1685. }
  1686. void IList.Clear ()
  1687. {
  1688. throw new NotSupportedException ();
  1689. }
  1690. bool IList.Contains (object selectedIndex)
  1691. {
  1692. throw new NotImplementedException ();
  1693. }
  1694. int IList.IndexOf (object selectedIndex)
  1695. {
  1696. return IndexOf ((int) selectedIndex);
  1697. }
  1698. void IList.Insert (int index, object value)
  1699. {
  1700. throw new NotSupportedException ();
  1701. }
  1702. void IList.Remove (object value)
  1703. {
  1704. throw new NotSupportedException ();
  1705. }
  1706. void IList.RemoveAt (int index)
  1707. {
  1708. throw new NotSupportedException ();
  1709. }
  1710. public int IndexOf (int selectedIndex)
  1711. {
  1712. return object_items.IndexOf (selectedIndex);
  1713. }
  1714. public virtual IEnumerator GetEnumerator ()
  1715. {
  1716. return object_items.GetEnumerator ();
  1717. }
  1718. #endregion Public Methods
  1719. #region Private Methods
  1720. internal void AddObject (object obj)
  1721. {
  1722. object_items.Add (obj);
  1723. }
  1724. internal void ClearObjects ()
  1725. {
  1726. object_items.Clear ();
  1727. }
  1728. internal void ReCreate ()
  1729. {
  1730. object_items.Clear ();
  1731. for (int i = 0; i < owner.Items.Count; i++) {
  1732. ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
  1733. if (item.Selected)
  1734. object_items.Add (owner.Items[item.Index]);
  1735. }
  1736. }
  1737. internal void RemoveObject (object obj)
  1738. {
  1739. object_items.Remove (obj);
  1740. }
  1741. #endregion Private Methods
  1742. }
  1743. }
  1744. }