1 //------------------------------------------------------------------------------ 2 // ssgui: a Java GUI interface for viewing, selecting, and downloading matrices 3 // from the SuiteSparse Matrix Collection. To compile this program, type the 4 // following in your OS command window: 5 // 6 // javac ssgui.java 7 // jar cfe ssgui.jar ssgui *.class sshelp.html 8 // 9 // You can then delete the *.class files. To run the program, type: 10 // 11 // java -jar ssgui.jar 12 // 13 // In all platforms except Windows (Mac, Linux, Solaris, ...) compile with: 14 // 15 // make 16 // 17 // and run with 18 // 19 // make run 20 // 21 //------------------------------------------------------------------------------ 22 // Changing the default parameters for ssgui: 23 //------------------------------------------------------------------------------ 24 // 25 // The following parameters of ssgui can be changed by editing this file and 26 // recompiling (see the comments "default settings" below in the code). 27 // Each setting is a string: 28 // 29 // sssite: URL for the SuiteSparse Matrix Collection 30 // default is sssite = "https://sparse.tamu.edu" ; 31 // 32 // ssarchive: directory containing your copy of the collection. 33 // If blank, then it defaults to the directory containing ssgui. 34 // 35 // refresh: refresh time, in days, for updating the index. use INF to 36 // never refresh 37 // 38 // proxy_server: HTTP proxy server. If none (default), then leave blank. 39 // 40 // proxy port: default is 80 if left blank 41 // 42 // Copyright (c) 2009-2019, Timothy A. Davis. See sshelp.html for the license, 43 // and for help on how to use this program, or click "Help" in the GUI. 44 //------------------------------------------------------------------------------ 45 46 import java.io.* ; 47 import java.util.* ; 48 import java.text.* ; 49 import java.net.* ; 50 import javax.swing.* ; 51 import javax.swing.table.* ; 52 import javax.swing.event.* ; 53 import java.awt.* ; 54 import java.awt.event.* ; 55 56 public class ssgui extends JFrame 57 { 58 59 //-------------------------------------------------------------------------- 60 // private variables, accessible to all methods in this class 61 //-------------------------------------------------------------------------- 62 63 private static final String 64 ssstats = "files/ssstats.csv", 65 ssindex = "files/ss_index.mat", 66 all_kinds = "(all kinds)", all_groups = "(all groups)" ; 67 private static final int K = 1024, M = K*K, buffersize = K, 68 MSEC_PER_DAY = 86400000 ; 69 70 private static long INF = Long.MAX_VALUE ; 71 72 private long refresh ; 73 private int nselected ; 74 private int [ ] download_ids = null ; 75 private boolean gui_ready, downloading, cancel, get_icons ; 76 private boolean debug = false ; 77 78 private matrix_Table_Model matrix_model = null ; 79 80 private File mat, MM, RB, iconDir ; 81 private String [ ] Kinds, Groups ; 82 private Object [ ][ ] Stats ; 83 84 private Date today, last_download ; 85 86 // files and input/output streams 87 private static String ftemp_name = null ; 88 private static BufferedOutputStream ftemp_out = null ; 89 private static BufferedInputStream url_in = null ; 90 private static BufferedReader in_reader = null ; 91 private static PrintWriter print_out = null ; 92 private static String sssite, ssarchive, proxy_server, proxy_port ; 93 94 // Java Swing components available to all methods in this class: 95 private JTable matrix_Table ; 96 private JButton download_Button, cancel_Button ; 97 private JTextField minrow_Field, maxrow_Field, mincol_Field, maxcol_Field, 98 minnentries_Field, maxnentries_Field, minpsym_Field, maxpsym_Field, 99 minnsym_Field, maxnsym_Field ; 100 private JRadioButton posdef_yes_Button, posdef_no_Button, 101 posdef_either_Button, nd_yes_Button, nd_no_Button, nd_either_Button, 102 real_yes_Button, real_no_Button, real_either_Button, 103 shape_square_Button, shape_rect_Button, shape_either_Button ; 104 private JLabel nselected_Label, progress_size_Label, icon_Label ; 105 private JCheckBox format_mat_Button, format_mm_Button, format_rb_Button ; 106 private JProgressBar progress1_Bar, progress2_Bar ; 107 private JFileChooser chooser ; 108 private JList Group_List, Kind_List ; 109 110 //-------------------------------------------------------------------------- 111 // create the GUI 112 //-------------------------------------------------------------------------- 113 ssgui( )114 private ssgui ( ) 115 { 116 gui_ready = false ; 117 downloading = false ; 118 cancel = false ; 119 final Font plain_Font = new Font ("SansSerif", Font.PLAIN, 12) ; 120 final Font small_Font = new Font ("SansSerif", Font.PLAIN, 10) ; 121 today = new Date ( ) ; 122 last_download = new Date ( ) ; 123 124 //---------------------------------------------------------------------- 125 // default settings. Edit this file and recompile to change them. 126 //---------------------------------------------------------------------- 127 128 // If ssarchive is blank, then it defaults to the current directory. 129 ssarchive = "" ; 130 131 // URL for the SuiteSparse Matrix Collection 132 sssite = "https://sparse.tamu.edu" ; 133 134 // refresh time, in days. use INF to never refresh 135 refresh = 30 ; 136 137 // HTTP proxy server. If none (default), then leave blank. 138 proxy_server = "" ; 139 140 // proxy port (default is 80 if left blank) 141 proxy_port = "" ; 142 143 //---------------------------------------------------------------------- 144 //---------------------------------------------------------------------- 145 146 // set up the HTTP proxy 147 if (proxy_server.length ( ) > 0) 148 { 149 if (proxy_port.length ( ) == 0) 150 { 151 proxy_port = "80" ; 152 } 153 // set the proxy server and port 154 System.setProperty ("proxySet", "true" ) ; 155 System.setProperty ("http.proxyHost", proxy_server) ; 156 System.setProperty ("http.proxyPort", proxy_port) ; 157 } 158 159 // ssarchive defaults to current working directory, if empty 160 if (ssarchive.length ( ) == 0) 161 { 162 ssarchive = System.getProperty ("user.dir") ; 163 } 164 ssarchive = ssarchive.replace ('\\', File.separatorChar) ; 165 ssarchive = ssarchive.replace ('/', File.separatorChar) ; 166 char c = ssarchive.charAt (ssarchive.length ( ) - 1) ; 167 if (c != File.separatorChar) 168 { 169 ssarchive += File.separatorChar ; 170 } 171 172 if (debug) 173 { 174 System.out.println ("") ; 175 System.out.println ("ssgui, debugging enabled.") ; 176 System.out.println ("local archive: [" + ssarchive + "]") ; 177 System.out.println ("ss url: [" + sssite + "]") ; 178 System.out.println ("refresh: [" + refresh + "]") ; 179 System.out.println ("proxy server: [" + proxy_server + "]") ; 180 System.out.println ("proxy port: [" + proxy_port + "]") ; 181 } 182 183 //---------------------------------------------------------------------- 184 // make sure the top-level directories exist 185 186 mat = CheckDir ("mat") ; 187 MM = CheckDir ("MM") ; 188 RB = CheckDir ("RB") ; 189 iconDir = CheckDir ("files") ; 190 191 //---------------------------------------------------------------------- 192 // read in the matrix statistics 193 194 Stats = load_ssstats ( ) ; 195 196 if (Stats == null || 197 ((today.getTime ( ) - last_download.getTime ( )) / MSEC_PER_DAY 198 > refresh)) 199 { 200 // ssstats file is missing, or old. Download both 201 // files/ssstats.csv and mat/ss_index.mat. 202 Stats = download_matrix_stats ( ) ; 203 if (debug) System.out.println ("downloading new ssstats.csv file") ; 204 } 205 206 if (Stats == null) 207 { 208 // display error dialog and quit 209 JOptionPane.showMessageDialog (this, 210 "Download of matrix statistics file failed.", 211 "Error", JOptionPane.ERROR_MESSAGE) ; 212 System.exit (-1) ; 213 } 214 215 //---------------------------------------------------------------------- 216 // set the title, and close on [x] 217 218 setTitle ("ssgui: SuiteSparse Matrix Collection") ; 219 setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE) ; 220 221 //---------------------------------------------------------------------- 222 // selection buttons 223 224 JPanel select_Button_Panel = new JPanel ( ) ; 225 226 JButton select_Button = new JButton ("Select") ; 227 JButton unselect_Button = new JButton ("Deselect") ; 228 JButton reset_Button = new JButton ("Reset criteria") ; 229 JButton clear_Button = new JButton ("Clear selections") ; 230 JButton help_Button = new JButton ("Help") ; 231 232 select_Button_Panel.add (select_Button) ; 233 select_Button_Panel.add (unselect_Button) ; 234 select_Button_Panel.add (reset_Button) ; 235 select_Button_Panel.add (clear_Button) ; 236 select_Button_Panel.add (help_Button) ; 237 238 select_Button.setToolTipText 239 ("Click to add matrices that fit the criteria to your selection.") ; 240 unselect_Button.setToolTipText ("Click to remove matrices " + 241 "that fit the criteria from your selection.") ; 242 reset_Button.setToolTipText ("Click to reset criteria, above. " + 243 "Prior selections, below, are not cleared.") ; 244 clear_Button.setToolTipText ("Click to clear selections, below. " + 245 "Criteria, above, is not reset).") ; 246 help_Button.setToolTipText ("For help, click here") ; 247 248 select_Button.addActionListener 249 ( 250 new ActionListener ( ) 251 { 252 public void actionPerformed (ActionEvent e) 253 { 254 make_selection (true) ; 255 } 256 } 257 ) ; 258 259 unselect_Button.addActionListener 260 ( 261 new ActionListener ( ) 262 { 263 public void actionPerformed (ActionEvent e) 264 { 265 make_selection (false) ; 266 } 267 } 268 ) ; 269 270 reset_Button.addActionListener 271 ( 272 new ActionListener ( ) 273 { 274 public void actionPerformed (ActionEvent e) 275 { 276 reset_Button_action (e) ; 277 } 278 } 279 ) ; 280 281 clear_Button.addActionListener 282 ( 283 new ActionListener ( ) 284 { 285 public void actionPerformed (ActionEvent e) 286 { 287 clear_Button_action (e) ; 288 } 289 } 290 ) ; 291 292 help_Button.addActionListener 293 ( 294 new ActionListener ( ) 295 { 296 public void actionPerformed (ActionEvent e) 297 { 298 help_Button_action (e) ; 299 } 300 } 301 ) ; 302 303 //---------------------------------------------------------------------- 304 // download button and format options 305 306 JPanel format_Panel = new JPanel ( ) ; 307 308 format_mat_Button = new JCheckBox ("MATLAB (mat)") ; 309 format_mm_Button = new JCheckBox ("Matrix Market (MM)") ; 310 format_rb_Button = new JCheckBox ("Rutherford/Boeing (RB) ") ; 311 312 format_mat_Button.setSelected (true) ; 313 314 format_mat_Button.setToolTipText ("Download in MATLAB *.mat format.") ; 315 format_mm_Button.setToolTipText ("Download in Matrix Market.") ; 316 format_rb_Button.setToolTipText 317 ("Download in Rutherford/Boeing format.") ; 318 319 nselected = 0 ; 320 nselected_Label = new JLabel ( ) ; 321 download_Button = new JButton ("Download") ; 322 323 format_Panel.add (download_Button) ; 324 format_Panel.add (format_mat_Button) ; 325 format_Panel.add (format_mm_Button) ; 326 format_Panel.add (format_rb_Button) ; 327 format_Panel.add (nselected_Label) ; 328 format_Panel.setMaximumSize (new Dimension (0,0)) ; 329 330 // progress bar and cancel button 331 FlowLayout progress_Layout = new FlowLayout (FlowLayout.LEADING) ; 332 JPanel progress_Panel = new JPanel (progress_Layout) ; 333 334 cancel_Button = new JButton ("Cancel") ; 335 cancel_Button.setEnabled (false) ; 336 progress1_Bar = new JProgressBar ( ) ; 337 progress2_Bar = new JProgressBar ( ) ; 338 progress_size_Label = new JLabel ("") ; 339 progress1_Bar.setMinimumSize (new Dimension (200,16)) ; 340 progress2_Bar.setMinimumSize (new Dimension (200,16)) ; 341 progress_Panel.add (cancel_Button) ; 342 progress_Panel.add (new JLabel (" Overall progress:")) ; 343 progress_Panel.add (progress1_Bar) ; 344 progress_Panel.add (new JLabel (" Current file:")) ; 345 progress_Panel.add (progress2_Bar) ; 346 progress_Panel.add (progress_size_Label) ; 347 progress_Panel.setMaximumSize (new Dimension (0,0)) ; 348 cancel_Button.setToolTipText ("No downloads in progress.") ; 349 350 download_Button.addActionListener 351 ( 352 new ActionListener ( ) 353 { 354 public void actionPerformed (ActionEvent e) 355 { 356 download_Button_action (e) ; 357 } 358 } 359 ) ; 360 361 cancel_Button.addActionListener 362 ( 363 new ActionListener ( ) 364 { 365 public void actionPerformed (ActionEvent e) 366 { 367 cancel_Button_action (e) ; 368 } 369 } 370 ) ; 371 372 JPanel download_Panel = new JPanel ( ) ; 373 GroupLayout layout3 = new GroupLayout (download_Panel) ; 374 download_Panel.setLayout (layout3) ; 375 376 layout3.setAutoCreateGaps (true) ; 377 layout3.setAutoCreateContainerGaps (false) ; 378 379 layout3.setHorizontalGroup 380 ( 381 layout3.createParallelGroup (GroupLayout.Alignment.LEADING) 382 .addComponent (format_Panel) 383 .addComponent (progress_Panel) 384 ) ; 385 386 layout3.setVerticalGroup 387 ( 388 layout3.createSequentialGroup ( ) 389 .addComponent (format_Panel) 390 .addComponent (progress_Panel) 391 ) ; 392 393 download_Panel.setBorder 394 (BorderFactory.createTitledBorder ("download")) ; 395 download_Panel.setMaximumSize (new Dimension (0,0)) ; 396 397 //---------------------------------------------------------------------- 398 // panel for m, n, nentries, psym, and nsym 399 400 // # of rows 401 minrow_Field = new JTextField ("") ; 402 JLabel rowlabel = new JLabel (" \u2264 number of rows \u2264 ") ; 403 maxrow_Field = new JTextField ("") ; 404 minrow_Field.setColumns (16) ; 405 maxrow_Field.setColumns (16) ; 406 minrow_Field.setToolTipText ("Leave blank for 'zero'.") ; 407 maxrow_Field.setToolTipText ("Leave blank for 'infinite'.") ; 408 minrow_Field.setMinimumSize (new Dimension (120,0)) ; 409 maxrow_Field.setMinimumSize (new Dimension (120,0)) ; 410 411 // # of columns 412 mincol_Field = new JTextField ("") ; 413 JLabel collabel = new JLabel (" \u2264 number of columns \u2264 ") ; 414 maxcol_Field = new JTextField ("") ; 415 mincol_Field.setColumns (16) ; 416 maxcol_Field.setColumns (16) ; 417 mincol_Field.setToolTipText ("Leave blank for 'zero'.") ; 418 maxcol_Field.setToolTipText ("Leave blank for 'infinite'.") ; 419 mincol_Field.setMinimumSize (new Dimension (120,0)) ; 420 maxcol_Field.setMinimumSize (new Dimension (120,0)) ; 421 422 // # of entries 423 minnentries_Field = new JTextField ("") ; 424 JLabel nentrieslabel = new JLabel (" \u2264 number of entries \u2264 "); 425 maxnentries_Field = new JTextField ("") ; 426 minnentries_Field.setColumns (16) ; 427 maxnentries_Field.setColumns (16) ; 428 minnentries_Field.setToolTipText ("Leave blank for 'zero'.") ; 429 maxnentries_Field.setToolTipText ("Leave blank for 'infinite'.") ; 430 minnentries_Field.setMinimumSize (new Dimension (120,0)) ; 431 maxnentries_Field.setMinimumSize (new Dimension (120,0)) ; 432 433 // pattern symmetry 434 minpsym_Field = new JTextField ("0.0") ; 435 JLabel psymlabel = new JLabel (" \u2264 pattern symmetry \u2264 ") ; 436 maxpsym_Field = new JTextField ("1.0") ; 437 minpsym_Field.setColumns (16) ; 438 maxpsym_Field.setColumns (16) ; 439 maxpsym_Field.setToolTipText ( 440 "Refers to position of entries, not their values.\n" + 441 "1 = perfectly symmetric pattern, 0 = perfectly unsymmetric pattern.") ; 442 minpsym_Field.setMinimumSize (new Dimension (120,0)) ; 443 maxpsym_Field.setMinimumSize (new Dimension (120,0)) ; 444 445 // numerical symmetry 446 minnsym_Field = new JTextField ("0.0") ; 447 JLabel nsymlabel = new JLabel (" \u2264 numerical symmetry \u2264 ") ; 448 maxnsym_Field = new JTextField ("1.0") ; 449 minnsym_Field.setColumns (16) ; 450 maxnsym_Field.setColumns (16) ; 451 maxnsym_Field.setToolTipText ( 452 "1 means A=A', 0 means no nonzero entry A(i,j) = A(j,i).") ; 453 minnsym_Field.setMinimumSize (new Dimension (120,0)) ; 454 maxnsym_Field.setMinimumSize (new Dimension (120,0)) ; 455 456 JPanel range_Panel = new JPanel ( ) ; 457 GroupLayout layout5 = new GroupLayout (range_Panel) ; 458 range_Panel.setLayout (layout5) ; 459 layout5.setAutoCreateGaps (false) ; 460 layout5.setAutoCreateContainerGaps (false) ; 461 462 layout5.setHorizontalGroup 463 ( 464 layout5.createSequentialGroup ( ) 465 .addGroup 466 ( 467 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 468 .addComponent (minrow_Field) 469 .addComponent (mincol_Field) 470 .addComponent (minnentries_Field) 471 .addComponent (minpsym_Field) 472 .addComponent (minnsym_Field) 473 ) 474 .addGroup 475 ( 476 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 477 .addComponent (rowlabel) 478 .addComponent (collabel) 479 .addComponent (nentrieslabel) 480 .addComponent (psymlabel) 481 .addComponent (nsymlabel) 482 ) 483 .addGroup 484 ( 485 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 486 .addComponent (maxrow_Field) 487 .addComponent (maxcol_Field) 488 .addComponent (maxnentries_Field) 489 .addComponent (maxpsym_Field) 490 .addComponent (maxnsym_Field) 491 ) 492 ) ; 493 494 layout5.setVerticalGroup 495 ( 496 layout5.createSequentialGroup ( ) 497 498 .addGroup 499 ( 500 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 501 .addComponent (minrow_Field) 502 .addComponent (rowlabel) 503 .addComponent (maxrow_Field) 504 ) 505 .addGroup 506 ( 507 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 508 .addComponent (mincol_Field) 509 .addComponent (collabel) 510 .addComponent (maxcol_Field) 511 ) 512 .addGroup 513 ( 514 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 515 .addComponent (minnentries_Field) 516 .addComponent (nentrieslabel) 517 .addComponent (maxnentries_Field) 518 ) 519 .addGroup 520 ( 521 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 522 .addComponent (minpsym_Field) 523 .addComponent (psymlabel) 524 .addComponent (maxpsym_Field) 525 ) 526 .addGroup 527 ( 528 layout5.createParallelGroup (GroupLayout.Alignment.LEADING) 529 .addComponent (minnsym_Field) 530 .addComponent (nsymlabel) 531 .addComponent (maxnsym_Field) 532 ) 533 534 ) ; 535 536 range_Panel.setMaximumSize (new Dimension (0,0)) ; 537 // range_Panel.setBorder (BorderFactory.createTitledBorder ("range")) ; 538 539 //---------------------------------------------------------------------- 540 // checkbox panel for posdef, ND, real, and format 541 542 // square or rectangular 543 JLabel shape_label = new JLabel ("shape ") ; 544 shape_square_Button = new JRadioButton ("square ") ; 545 shape_rect_Button = new JRadioButton ("rectangular ") ; 546 shape_either_Button = new JRadioButton ("either ") ; 547 shape_either_Button.setSelected (true) ; 548 ButtonGroup shape_group = new ButtonGroup ( ) ; 549 shape_group.add (shape_square_Button) ; 550 shape_group.add (shape_rect_Button) ; 551 shape_group.add (shape_either_Button) ; 552 shape_square_Button.setToolTipText 553 ("Select 'yes' for square matrices.") ; 554 shape_rect_Button.setToolTipText 555 ("Select 'no' for rectangular matrices only.") ; 556 shape_either_Button.setToolTipText 557 ("Select 'either' for any matrix.") ; 558 559 // positive definite 560 JLabel posdef_label = new JLabel ("positive definite? ") ; 561 posdef_yes_Button = new JRadioButton ("yes") ; 562 posdef_no_Button = new JRadioButton ("no") ; 563 posdef_either_Button = new JRadioButton ("either") ; 564 posdef_either_Button.setSelected (true) ; 565 ButtonGroup posdef_group = new ButtonGroup ( ) ; 566 posdef_group.add (posdef_yes_Button) ; 567 posdef_group.add (posdef_no_Button) ; 568 posdef_group.add (posdef_either_Button) ; 569 570 posdef_yes_Button.setToolTipText 571 ("Select 'yes' for symmetric positive definite matrices only.") ; 572 posdef_no_Button.setToolTipText 573 ("Select 'no' for non-positive definite matrices only.") ; 574 posdef_either_Button.setToolTipText 575 ("Select 'either' for any matrix.") ; 576 577 // 2D/3D 578 JLabel nd_label = new JLabel ("2D/3D discretization? ") ; 579 nd_yes_Button = new JRadioButton ("yes") ; 580 nd_no_Button = new JRadioButton ("no") ; 581 nd_either_Button = new JRadioButton ("either") ; 582 nd_either_Button.setSelected (true) ; 583 ButtonGroup nd_group = new ButtonGroup ( ) ; 584 nd_group.add (nd_yes_Button) ; 585 nd_group.add (nd_no_Button) ; 586 nd_group.add (nd_either_Button) ; 587 588 nd_yes_Button.setToolTipText 589 ("Select 'yes' for matrices " + 590 "arising from 2D or 3D discretizations only.") ; 591 nd_no_Button.setToolTipText 592 ("Select 'no' to exclude matrices " + 593 "arising from 2D or 3D discretizations.") ; 594 nd_either_Button.setToolTipText ("Select 'either' for any matrix.") ; 595 596 // real or complex 597 JLabel real_label = new JLabel ("real or complex? ") ; 598 real_yes_Button = new JRadioButton ("real") ; 599 real_no_Button = new JRadioButton ("complex") ; 600 real_either_Button = new JRadioButton ("either") ; 601 real_either_Button.setSelected (true) ; 602 ButtonGroup real_group = new ButtonGroup ( ) ; 603 real_group.add (real_yes_Button) ; 604 real_group.add (real_no_Button) ; 605 real_group.add (real_either_Button) ; 606 607 real_yes_Button.setToolTipText 608 ("Select 'real' for real matrices only (includes integer and binary).") ; 609 real_no_Button.setToolTipText 610 ("Select 'complex' for complex matrices only.") ; 611 real_either_Button.setToolTipText 612 ("Select 'either' for any matrix.") ; 613 614 JPanel check_Panel = new JPanel ( ) ; 615 GroupLayout layout4 = new GroupLayout (check_Panel) ; 616 check_Panel.setLayout (layout4) ; 617 layout4.setAutoCreateGaps (false) ; 618 layout4.setAutoCreateContainerGaps (false) ; 619 620 layout4.setHorizontalGroup 621 ( 622 layout4.createSequentialGroup ( ) 623 .addGroup 624 ( 625 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 626 .addComponent (shape_label) 627 .addComponent (posdef_label) 628 .addComponent (nd_label) 629 .addComponent (real_label) 630 ) 631 .addGroup 632 ( 633 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 634 .addComponent (shape_square_Button) 635 .addComponent (posdef_yes_Button) 636 .addComponent (nd_yes_Button) 637 .addComponent (real_yes_Button) 638 ) 639 .addGroup 640 ( 641 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 642 .addComponent (shape_rect_Button) 643 .addComponent (posdef_no_Button) 644 .addComponent (nd_no_Button) 645 .addComponent (real_no_Button) 646 ) 647 .addGroup 648 ( 649 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 650 .addComponent (shape_either_Button) 651 .addComponent (posdef_either_Button) 652 .addComponent (nd_either_Button) 653 .addComponent (real_either_Button) 654 ) 655 ) ; 656 657 layout4.setVerticalGroup 658 ( 659 layout4.createSequentialGroup ( ) 660 .addGroup 661 ( 662 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 663 .addComponent (shape_label) 664 .addComponent (shape_square_Button) 665 .addComponent (shape_rect_Button) 666 .addComponent (shape_either_Button) 667 ) 668 .addGroup 669 ( 670 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 671 .addComponent (posdef_label) 672 .addComponent (posdef_yes_Button) 673 .addComponent (posdef_no_Button) 674 .addComponent (posdef_either_Button) 675 ) 676 .addGroup 677 ( 678 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 679 .addComponent (nd_label) 680 .addComponent (nd_yes_Button) 681 .addComponent (nd_no_Button) 682 .addComponent (nd_either_Button) 683 ) 684 .addGroup 685 ( 686 layout4.createParallelGroup (GroupLayout.Alignment.LEADING) 687 .addComponent (real_label) 688 .addComponent (real_yes_Button) 689 .addComponent (real_no_Button) 690 .addComponent (real_either_Button) 691 ) 692 ) ; 693 694 check_Panel.setMaximumSize (new Dimension (0,0)) ; 695 696 //---------------------------------------------------------------------- 697 // Group and Kind lists 698 699 Kinds = FindKinds ( ) ; 700 Groups = FindGroups ( ) ; 701 702 // Group_List = new JList ((Object [ ]) Groups) ; 703 // Kind_List = new JList ((Object [ ]) Kinds) ; 704 Group_List = new JList<String> (Groups) ; 705 Kind_List = new JList<String> (Kinds) ; 706 707 JScrollPane Group_Pane = new JScrollPane (Group_List) ; 708 JScrollPane Kind_Pane = new JScrollPane (Kind_List) ; 709 710 Kind_Pane.setBorder (BorderFactory.createTitledBorder ("kind")) ; 711 Group_Pane.setBorder (BorderFactory.createTitledBorder ("group")) ; 712 713 Group_List.setFont (plain_Font) ; 714 Kind_List.setFont (plain_Font) ; 715 716 Group_Pane.setVerticalScrollBarPolicy 717 (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS) ; 718 Kind_Pane.setVerticalScrollBarPolicy 719 (ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS) ; 720 721 Group_List.setVisibleRowCount (5) ; 722 Kind_List.setVisibleRowCount (5) ; 723 724 JPanel list_Panel = new JPanel ( ) ; 725 GroupLayout layout9 = new GroupLayout (list_Panel) ; 726 list_Panel.setLayout (layout9) ; 727 728 layout9.setAutoCreateGaps (true) ; 729 layout9.setAutoCreateContainerGaps (false) ; 730 731 layout9.setHorizontalGroup 732 ( 733 layout9.createSequentialGroup ( ) 734 .addComponent (Group_Pane) 735 .addComponent (Kind_Pane) 736 ) ; 737 738 layout9.setVerticalGroup 739 ( 740 layout9.createParallelGroup (GroupLayout.Alignment.LEADING) 741 .addComponent (Group_Pane) 742 .addComponent (Kind_Pane) 743 ) ; 744 745 list_Panel.setMinimumSize (new Dimension (450,150)) ; 746 747 //---------------------------------------------------------------------- 748 // selection panel 749 JPanel selection_Panel = new JPanel ( ) ; 750 GroupLayout layout2 = new GroupLayout (selection_Panel) ; 751 selection_Panel.setLayout (layout2) ; 752 layout2.setAutoCreateGaps (true) ; 753 layout2.setAutoCreateContainerGaps (false) ; 754 layout2.setHorizontalGroup 755 ( 756 layout2.createParallelGroup (GroupLayout.Alignment.LEADING) 757 .addComponent (range_Panel) 758 .addComponent (check_Panel) 759 .addComponent (list_Panel) 760 .addComponent (select_Button_Panel) 761 ) ; 762 layout2.setVerticalGroup 763 ( 764 layout2.createSequentialGroup ( ) 765 .addComponent (range_Panel) 766 .addComponent (check_Panel) 767 .addComponent (list_Panel) 768 .addComponent (select_Button_Panel) 769 ) ; 770 selection_Panel.setBorder 771 (BorderFactory.createTitledBorder ("selection criteria")) ; 772 selection_Panel.setMaximumSize (new Dimension (0,0)) ; 773 774 //---------------------------------------------------------------------- 775 // create the table of matrices 776 777 matrix_model = new matrix_Table_Model ( ) ; 778 matrix_Table = new JTable (matrix_model) 779 { 780 // table header tool tips 781 protected JTableHeader createDefaultTableHeader ( ) 782 { 783 return new JTableHeader (columnModel) 784 { 785 public String getToolTipText (MouseEvent e) 786 { 787 String tip = null ; 788 java.awt.Point p = e.getPoint ( ) ; 789 int i = columnModel.getColumnIndexAtX (p.x) ; 790 int j = columnModel.getColumn (i).getModelIndex ( ) ; 791 return matrix_column_tooltips [j] ; 792 } 793 } ; 794 } 795 } ; 796 797 JTableHeader header = matrix_Table.getTableHeader ( ) ; 798 final TableCellRenderer hr = header.getDefaultRenderer ( ) ; 799 header.setDefaultRenderer 800 ( 801 new TableCellRenderer ( ) 802 { 803 public Component getTableCellRendererComponent (JTable table, 804 Object value, boolean isSelected, boolean hasFocus, 805 int row, int column) 806 { 807 Component co = hr.getTableCellRendererComponent ( 808 table, value, isSelected, hasFocus, row, column) ; 809 co.setFont (small_Font) ; 810 return (co) ; 811 } 812 } 813 ) ; 814 815 matrix_model.load_data (Stats) ; 816 817 //---------------------------------------------------------------------- 818 // popup menu for the table 819 820 JPopupMenu popup = new JPopupMenu ( ) ; 821 822 JMenuItem select_menuItem = 823 new JMenuItem ("Select highlighted matrices") ; 824 select_menuItem.addActionListener 825 ( 826 new ActionListener ( ) 827 { 828 public void actionPerformed (ActionEvent e) 829 { 830 popup_action (e, true) ; 831 } 832 } 833 ) ; 834 835 JMenuItem unselect_menuItem = 836 new JMenuItem ("Deselect highlighted matrices") ; 837 unselect_menuItem.addActionListener 838 ( 839 new ActionListener ( ) 840 { 841 public void actionPerformed (ActionEvent e) 842 { 843 popup_action (e, false) ; 844 } 845 } 846 ) ; 847 848 JMenuItem exportcsv_menuItem = 849 new JMenuItem ("Export selected matrices as CSV file") ; 850 exportcsv_menuItem.addActionListener 851 ( 852 new ActionListener ( ) 853 { 854 public void actionPerformed (ActionEvent e) 855 { 856 export_list_action (e, true) ; 857 } 858 } 859 ) ; 860 861 JMenuItem exportm_menuItem = 862 new JMenuItem ("Export selected matrices as MATLAB *.m file") ; 863 exportm_menuItem.addActionListener 864 ( 865 new ActionListener ( ) 866 { 867 public void actionPerformed (ActionEvent e) 868 { 869 export_list_action (e, false) ; 870 } 871 } 872 ) ; 873 874 popup.add (select_menuItem) ; 875 popup.add (unselect_menuItem) ; 876 popup.add (exportcsv_menuItem) ; 877 popup.add (exportm_menuItem) ; 878 879 // Add listener to components that can bring up popup menus. 880 matrix_Table.addMouseListener (new matrix_Table_PopupListener (popup)) ; 881 882 //---------------------------------------------------------------------- 883 // set default column widths 884 885 int [ ] columnwidth = { 886 40, // 0:select 887 30, // 1:mat 888 25, // 2:MM 889 25, // 3:RB 890 38, // 4:id 891 110, // 5:Group 892 150, // 6:Name 893 70, // 7:nrows 894 70, // 8:ncols 895 70, // 9:nentries 896 40, // 10:isReal 897 40, // 11:isBinary 898 40, // 12:isND 899 40, // 13:posdef 900 50, // 14:psym 901 50, // 15:nsym 902 200 } ; // 16:kind 903 904 TableColumn column = null ; 905 for (int col = 0 ; col < 17 ; col++) 906 { 907 column = matrix_Table.getColumnModel ( ).getColumn (col) ; 908 column.setPreferredWidth (columnwidth [col]) ; 909 } 910 911 //---------------------------------------------------------------------- 912 // set the view size, sort by id, and add the table to a scroll pane 913 914 matrix_Table.setPreferredScrollableViewportSize 915 (new Dimension (500,70)) ; 916 matrix_Table.setFillsViewportHeight (true) ; 917 matrix_Table.setAutoCreateRowSorter (true) ; 918 919 matrix_Table.getSelectionModel ( ) 920 .addListSelectionListener (new matrix_Table_RowListener ( )) ; 921 922 // sort by id 923 java.util.List <RowSorter.SortKey> sortKeys = 924 new ArrayList<RowSorter.SortKey> ( ) ; 925 sortKeys.add (new RowSorter.SortKey (4, SortOrder.ASCENDING)) ; 926 (matrix_Table.getRowSorter ( )).setSortKeys (sortKeys) ; 927 928 matrix_Table.getTableHeader ( ).setReorderingAllowed (false) ; 929 JScrollPane scroll_Pane = new JScrollPane (matrix_Table) ; 930 scroll_Pane.setBorder (BorderFactory.createTitledBorder (ssarchive)) ; 931 932 //---------------------------------------------------------------------- 933 // create the icon and display the default matrix 934 935 icon_Label = new JLabel ( ) ; 936 icon_Label.setFont (plain_Font) ; 937 icon_Label.setVerticalTextPosition (JLabel.BOTTOM) ; 938 icon_Label.setHorizontalTextPosition (JLabel.CENTER) ; 939 icon_Label.setBorder (BorderFactory.createTitledBorder ("matrix icon")); 940 update_icon ("HB/west0479") ; 941 942 //---------------------------------------------------------------------- 943 // create the top panel (selection panel and icon) 944 945 JPanel top_Panel = new JPanel ( ) ; 946 GroupLayout layout8 = new GroupLayout (top_Panel) ; 947 top_Panel.setLayout (layout8) ; 948 949 layout8.setAutoCreateGaps (true) ; 950 layout8.setAutoCreateContainerGaps (false) ; 951 952 layout8.setHorizontalGroup 953 ( 954 layout8.createSequentialGroup ( ) 955 .addComponent (selection_Panel) 956 .addComponent (icon_Label) 957 ) ; 958 959 layout8.setVerticalGroup 960 ( 961 layout8.createParallelGroup (GroupLayout.Alignment.LEADING) 962 .addComponent (selection_Panel) 963 .addComponent (icon_Label) 964 ) ; 965 966 top_Panel.setMaximumSize (new Dimension (0,0)) ; 967 968 //---------------------------------------------------------------------- 969 // create the root layout manager 970 971 Container pane = getContentPane ( ) ; 972 GroupLayout layout = new GroupLayout (pane) ; 973 pane.setLayout (layout) ; 974 layout.setAutoCreateGaps (true) ; 975 layout.setAutoCreateContainerGaps (false) ; 976 977 layout.setHorizontalGroup 978 ( 979 layout.createParallelGroup (GroupLayout.Alignment.LEADING) 980 .addComponent (top_Panel) 981 .addComponent (scroll_Pane) 982 .addComponent (download_Panel) 983 ) ; 984 985 layout.setVerticalGroup 986 ( 987 layout.createSequentialGroup ( ) 988 .addComponent (top_Panel) 989 .addComponent (scroll_Pane) 990 .addComponent (download_Panel) 991 ) ; 992 993 setSize (1100,750) ; 994 995 //---------------------------------------------------------------------- 996 // create the file chooser; not shown until "export" is chosen 997 998 chooser = new JFileChooser ( ) ; 999 chooser.setFileSelectionMode (JFileChooser.FILES_AND_DIRECTORIES) ; 1000 1001 gui_ready = true ; 1002 set_selected_label (true) ; 1003 1004 //---------------------------------------------------------------------- 1005 // start a thread to download any icons not present 1006 1007 get_all_icons ( ) ; 1008 } 1009 1010 //-------------------------------------------------------------------------- 1011 // yes/no/unknown 1012 //-------------------------------------------------------------------------- 1013 yes_no(int k)1014 private String yes_no (int k) 1015 { 1016 if (k < 0) 1017 { 1018 return ("?") ; 1019 } 1020 else if (k == 0) 1021 { 1022 return ("no") ; 1023 } 1024 else 1025 { 1026 return ("yes") ; 1027 } 1028 } 1029 1030 //-------------------------------------------------------------------------- 1031 // ternary 1032 //-------------------------------------------------------------------------- 1033 ternary(String s)1034 private int ternary (String s) 1035 { 1036 long k = Long.parseLong (s) ; 1037 if (k < 0) 1038 { 1039 return (-1) ; 1040 } 1041 else if (k == 0) 1042 { 1043 return (0) ; 1044 } 1045 else 1046 { 1047 return (1) ; 1048 } 1049 } 1050 1051 //-------------------------------------------------------------------------- 1052 // read the ssstats file 1053 //-------------------------------------------------------------------------- 1054 load_ssstats( )1055 private Object [ ][ ] load_ssstats ( ) 1056 { 1057 if (debug) System.out.println ("reading ssstats.csv file") ; 1058 Object [ ][ ] S = null ; 1059 int nmatrices = 0 ; 1060 in_reader = null ; 1061 try 1062 { 1063 // get the number of matrices in the ss Sparse Matrix Collection 1064 in_reader = new BufferedReader (new FileReader 1065 (fix_name (ssstats))) ; 1066 nmatrices = Integer.parseInt (in_reader.readLine ( )) ; 1067 // skip past the creation date and time 1068 String ignore = in_reader.readLine ( ) ; 1069 // get the time of last download from the file modification time 1070 last_download = 1071 new Date (new File (fix_name (ssstats)).lastModified ( )) ; 1072 } 1073 catch (Exception e) 1074 { 1075 // this is OK, for now, since we can try to download a new one 1076 if (debug) System.out.println ("reading ssstats.csv file failed") ; 1077 return (null) ; 1078 } 1079 try 1080 { 1081 // read the rest of the file 1082 S = new Object [nmatrices][13] ; 1083 for (int id = 1 ; id <= nmatrices ; id++) 1084 { 1085 // split the tokens by comma 1086 String [ ] r = (in_reader.readLine ( )).split (",") ; 1087 S [id-1][0] = id ; // id 1088 S [id-1][1] = r [0] ; // Group 1089 S [id-1][2] = r [1] ; // Name 1090 S [id-1][3] = Long.parseLong (r [2]) ; // nrows 1091 S [id-1][4] = Long.parseLong (r [3]) ; // ncols 1092 // NOTE: r [4] = nnz is now ignored, and r [12] used instead 1093 S [id-1][5] = Long.parseLong (r [12]) ; // nentries 1094 1095 S [id-1][6] = ternary (r [5]) ; // isReal 1096 S [id-1][7] = ternary (r [6]) ; // isBinary 1097 S [id-1][8] = ternary (r [7]) ; // isND 1098 S [id-1][9] = ternary (r [8]) ; // posdef 1099 1100 S [id-1][10] = Double.parseDouble (r [9]) ; // psym 1101 S [id-1][11] = Double.parseDouble (r [10]) ; // nsym 1102 S [id-1][12] = r [11] ; // kind 1103 } 1104 } 1105 catch (Exception e) 1106 { 1107 // this is OK, for now, since we can try to download a new one 1108 if (debug) System.out.println ("reading ssstats.csv file failed") ; 1109 return (null) ; 1110 } 1111 finally 1112 { 1113 close_reader (in_reader) ; 1114 } 1115 return (S) ; 1116 } 1117 1118 //-------------------------------------------------------------------------- 1119 // tool tips for each column of the matrix table 1120 //-------------------------------------------------------------------------- 1121 1122 protected String [ ] matrix_column_tooltips = 1123 { 1124 // 0:select: 1125 "Click to select a matrix. This is the only column you can edit.", 1126 "'x' if MAT format already downloaded", // 1:mat 1127 "'x' if MM format already downloaded", // 2:MM 1128 "'x' if RB format already downloaded", // 3:MM 1129 "matrix id", // 4:id 1130 "matrix group (typically a person or organization)",// 5:Group 1131 "matrix name (full name is Group/Name)", // 6:Name 1132 "# of rows in the matrix", // 7:nrows 1133 "# of columns in the matrix", // 8:ncols 1134 "# of entries in the matrix (both nonzeros and explicit zeros)", 1135 // 9:nentries 1136 "if the matrix is real (not complex)", // 10:isReal 1137 "if the matrix is binary", // 11:isBinary 1138 "if the matrix arises from a 2D/3D discretization", // 12:isND 1139 "if the matrix is symmetric positive definite", // 13:posdef 1140 // 14:psym: 1141 "symmetry of pattern (0: none, 1: pattern(A)=pattern(A')", 1142 "symmetry of nonzero values (0: none, 1: A=A'", // 15:nsym 1143 // 16:kind: 1144 "the matrix 'kind' is the problem domain from which it arises" 1145 } ; 1146 1147 //-------------------------------------------------------------------------- 1148 // control whether changes to the table cause updates to fire 1149 //-------------------------------------------------------------------------- 1150 1151 public boolean fire_status = true ; 1152 fire_updates(boolean fire)1153 public void fire_updates (boolean fire) 1154 { 1155 fire_status = fire ; 1156 if (fire) 1157 { 1158 // touch the table to force a fire 1159 set_table_value (get_table_value (1, 0), 1, 0) ; 1160 } 1161 } 1162 1163 //-------------------------------------------------------------------------- 1164 // table of matrix statistics 1165 //-------------------------------------------------------------------------- 1166 1167 class matrix_Table_Model extends AbstractTableModel 1168 { 1169 private String [ ] columnNames = 1170 { 1171 "select", "mat", "MM", "RB", 1172 "id", "Group", "Name", "# rows", "# cols", "# entries", "real", 1173 "binary", "2D/3D", "posdef", "psym", "nsym", "kind" } ; 1174 1175 private Object [ ][ ] data = null ; 1176 getColumnCount( )1177 public int getColumnCount ( ) 1178 { 1179 return (columnNames.length) ; 1180 } 1181 getRowCount( )1182 public int getRowCount ( ) 1183 { 1184 return (data.length) ; 1185 } 1186 getColumnName(int col)1187 public String getColumnName (int col) 1188 { 1189 return (columnNames [col]) ; 1190 } 1191 getValueAt(int row, int col)1192 public Object getValueAt (int row, int col) 1193 { 1194 return (data [row][col]) ; 1195 } 1196 isCellEditable(int row, int col)1197 public boolean isCellEditable (int row, int col) 1198 { 1199 // only the "select" column is edittable 1200 return (col == 0) ; 1201 } 1202 setValueAt(Object value, int row, int col)1203 public void setValueAt (Object value, int row, int col) 1204 { 1205 if (col == 0 && gui_ready && ((Boolean) data [row][0]) != value) 1206 { 1207 if ((Boolean) value == false) 1208 { 1209 // changing from selected to unselected 1210 nselected-- ; 1211 } 1212 else 1213 { 1214 // changing from unselected to selected 1215 nselected++ ; 1216 } 1217 set_selected_label (download_Button.isEnabled ( )) ; 1218 } 1219 data [row][col] = value ; 1220 if (fire_status) fireTableDataChanged ( ) ; 1221 } 1222 getColumnClass(int col)1223 public Class getColumnClass (int col) 1224 { 1225 return (getValueAt (0, col).getClass ( )) ; 1226 } 1227 load_data(Object [ ][ ] newstats)1228 public void load_data (Object [ ][ ] newstats) 1229 { 1230 // load the matrix table with all matrix statistics 1231 data = new Object [newstats.length][17] ; 1232 nselected = 0 ; 1233 for (int i = 0 ; i < newstats.length ; i++) 1234 { 1235 // i and j are in terms of the view, but the table is not yet 1236 // sorted because it is not yet visible 1237 data [i][0] = false ; // select column is false 1238 for (int j = 1 ; j < 4 ; j++) 1239 { 1240 // mat, MM, and RB, which can change later: 1241 data [i][j] = "-" ; 1242 } 1243 for (int j = 0 ; j < 13 ; j++) 1244 { 1245 // matrix stats, which do not change: 1246 // 4:id, 5:Group, 6:Name, 7:nrows, 8:ncols, 9:nentries, 1247 // 10:isreal, 11:isBinary, 12:isND, 13:posdef, 14: psym, 1248 // 15:nsym, 16:kind 1249 if (j >= 6 && j <= 9) 1250 { 1251 int k = (Integer) newstats [i][j] ; 1252 if (k < 0) 1253 { 1254 data [i][j+4] = " ?" ; 1255 } 1256 else if (k == 0) 1257 { 1258 data [i][j+4] = " no" ; 1259 } 1260 else 1261 { 1262 data [i][j+4] = " yes" ; 1263 } 1264 } 1265 else 1266 { 1267 data [i][j+4] = newstats [i][j] ; 1268 } 1269 } 1270 } 1271 fireTableDataChanged ( ) ; 1272 } 1273 } 1274 1275 //-------------------------------------------------------------------------- 1276 // get a value from the matrix table 1277 //-------------------------------------------------------------------------- 1278 get_table_value(int id, int j)1279 private Object get_table_value (int id, int j) 1280 { 1281 // id is in the range 1 to Stats.length. The model index is id-1. 1282 // Convert this to the row index of the view and then get the data. 1283 // j is in the range 0 to 16, and is the same in the view and the 1284 // model, since column rearranging is never done. 1285 1286 int i = matrix_Table.convertRowIndexToView (id-1) ; 1287 return (matrix_Table.getValueAt (i, j)) ; 1288 } 1289 1290 //-------------------------------------------------------------------------- 1291 // set a value in the matrix table 1292 //-------------------------------------------------------------------------- 1293 set_table_value(Object value, int id, int j)1294 private void set_table_value (Object value, int id, int j) 1295 { 1296 // just like get_table_value, setting the data instead of getting it 1297 1298 int i = matrix_Table.convertRowIndexToView (id-1) ; 1299 matrix_Table.setValueAt (value, i, j) ; 1300 } 1301 1302 //-------------------------------------------------------------------------- 1303 // get ids of highlighted matrices 1304 //-------------------------------------------------------------------------- 1305 get_highlighted_ids( )1306 private int [ ] get_highlighted_ids ( ) 1307 { 1308 // return a list of highlighted matrix id's 1309 1310 // get the highlighted row indices in the current view 1311 int [ ] highlighted = matrix_Table.getSelectedRows ( ) ; 1312 // convert the row view indices to matrix id's 1313 for (int k = 0 ; k < highlighted.length ; k++) 1314 { 1315 int i = highlighted [k] ; 1316 int id = 1 + matrix_Table.convertRowIndexToModel (i) ; 1317 highlighted [k] = id ; 1318 } 1319 return (highlighted) ; 1320 } 1321 1322 //-------------------------------------------------------------------------- 1323 // get ids of matrices selected for download 1324 //-------------------------------------------------------------------------- 1325 get_download_ids( )1326 private int [ ] get_download_ids ( ) 1327 { 1328 // get the list of ids to download, in view order 1329 nselected = 0 ; 1330 for (int i = 0 ; i < Stats.length ; i++) 1331 { 1332 if ((Boolean) matrix_Table.getValueAt (i, 0)) 1333 { 1334 nselected++ ; 1335 } 1336 } 1337 int [ ] downloads = new int [nselected] ; 1338 int k = 0 ; 1339 for (int i = 0 ; i < Stats.length ; i++) 1340 { 1341 if ((Boolean) matrix_Table.getValueAt (i, 0)) 1342 { 1343 int id = 1 + matrix_Table.convertRowIndexToModel (i) ; 1344 downloads [k++] = id ; 1345 } 1346 } 1347 return (downloads) ; 1348 } 1349 1350 //-------------------------------------------------------------------------- 1351 // set "Matrices selected:" label and download tool tip 1352 //-------------------------------------------------------------------------- 1353 set_selected_label(boolean enabled)1354 private void set_selected_label (boolean enabled) 1355 { 1356 if (gui_ready) 1357 { 1358 nselected_Label.setText 1359 (" Matrices selected: " + nselected + " ") ; 1360 download_Button.setEnabled (enabled) ; 1361 if (enabled) 1362 { 1363 if (nselected == 0) 1364 { 1365 download_Button.setToolTipText 1366 ("No matrices have been selected for download") ; 1367 } 1368 else if (nselected == 1) 1369 { 1370 download_Button.setToolTipText 1371 ("Click to download the single selected matrix") ; 1372 } 1373 else 1374 { 1375 download_Button.setToolTipText 1376 ("Click to download the " + nselected + 1377 " selected matrices") ; 1378 } 1379 } 1380 else 1381 { 1382 download_Button.setToolTipText ("Download in progress.") ; 1383 } 1384 } 1385 } 1386 1387 //-------------------------------------------------------------------------- 1388 // show matrix icon 1389 //-------------------------------------------------------------------------- 1390 show_highlighted_icon( )1391 private void show_highlighted_icon ( ) 1392 { 1393 // show icon of last entry in the highlighted list 1394 int [ ] highlighted = get_highlighted_ids ( ) ; 1395 int n = highlighted.length ; 1396 if (n > 0) 1397 { 1398 int id = highlighted [n-1] ; 1399 String Group = (String) Stats [id-1][1] ; 1400 String Name = (String) Stats [id-1][2] ; 1401 update_icon (Group + "/" + Name) ; 1402 } 1403 } 1404 1405 //-------------------------------------------------------------------------- 1406 // matrix table popup listener 1407 //-------------------------------------------------------------------------- 1408 1409 private class matrix_Table_PopupListener extends MouseAdapter 1410 { 1411 JPopupMenu pop ; 1412 matrix_Table_PopupListener(JPopupMenu popupMenu)1413 matrix_Table_PopupListener (JPopupMenu popupMenu) 1414 { 1415 pop = popupMenu ; 1416 } 1417 mousePressed(MouseEvent e)1418 public void mousePressed (MouseEvent e) 1419 { 1420 maybeShowPopup (e) ; 1421 } 1422 mouseReleased(MouseEvent e)1423 public void mouseReleased (MouseEvent e) 1424 { 1425 maybeShowPopup (e) ; 1426 } 1427 maybeShowPopup(MouseEvent e)1428 private void maybeShowPopup (MouseEvent e) 1429 { 1430 if (e.isPopupTrigger ( )) 1431 { 1432 pop.show (e.getComponent ( ), e.getX ( ), e.getY ( )) ; 1433 } 1434 } 1435 } 1436 1437 //-------------------------------------------------------------------------- 1438 // matrix table row listener 1439 //-------------------------------------------------------------------------- 1440 1441 private class matrix_Table_RowListener implements ListSelectionListener 1442 { valueChanged(ListSelectionEvent event)1443 public void valueChanged (ListSelectionEvent event) 1444 { 1445 if (event.getValueIsAdjusting ( )) 1446 { 1447 return ; 1448 } 1449 show_highlighted_icon ( ) ; 1450 } 1451 } 1452 1453 //-------------------------------------------------------------------------- 1454 // FindKinds: determine the set of all Problem kinds 1455 //-------------------------------------------------------------------------- 1456 FindKinds( )1457 private String [ ] FindKinds ( ) 1458 { 1459 Set<String> KindSet = new TreeSet<String> ( ) ; 1460 KindSet.add (all_kinds) ; 1461 for (int id = 1 ; id <= Stats.length ; id++) 1462 { 1463 KindSet.add (SimplifyKind ((String) Stats [id-1][12])) ; 1464 } 1465 return ((String [ ]) KindSet.toArray (new String [0])) ; 1466 } 1467 1468 //-------------------------------------------------------------------------- 1469 // FindGroups: determine the set of all groups 1470 //-------------------------------------------------------------------------- 1471 FindGroups( )1472 private String [ ] FindGroups ( ) 1473 { 1474 Set<String> GroupSet = new TreeSet<String> ( ) ; 1475 GroupSet.add (all_groups) ; 1476 for (int id = 1 ; id <= Stats.length ; id++) 1477 { 1478 GroupSet.add ((String) Stats [id-1][1]) ; 1479 } 1480 return ((String [ ]) GroupSet.toArray (new String [0])) ; 1481 } 1482 1483 //-------------------------------------------------------------------------- 1484 // SimplifyKind: remove extranneous terms from a string 1485 //-------------------------------------------------------------------------- 1486 SimplifyKind(String kind)1487 private String SimplifyKind (String kind) 1488 { 1489 // remove terms from a matrix-kind string 1490 String result = null ; 1491 String [ ] token = kind.split (" ") ; 1492 for (int i = 0 ; i < token.length ; i++) 1493 { 1494 if (! (token [i].equals ("subsequent") 1495 || token [i].equals ("sequence") 1496 || token [i].equals ("problem") 1497 || token [i].equals ("duplicate"))) 1498 { 1499 if (result == null) 1500 { 1501 result = token [i] ; 1502 } 1503 else 1504 { 1505 result = result + " " + token [i] ; 1506 } 1507 } 1508 } 1509 return (result) ; 1510 } 1511 1512 //-------------------------------------------------------------------------- 1513 // CheckDir: return a directory, creating it if it doesn't exist 1514 //-------------------------------------------------------------------------- 1515 CheckDir(String directory_name)1516 private File CheckDir (String directory_name) 1517 { 1518 File dir = new File (fix_name (directory_name)) ; 1519 if (!dir.isDirectory ( )) 1520 { 1521 dir.mkdirs ( ) ; 1522 } 1523 return (dir) ; 1524 } 1525 1526 //-------------------------------------------------------------------------- 1527 // CheckExistence: determine which files exist in the local file system 1528 //-------------------------------------------------------------------------- 1529 CheckExistence( )1530 private void CheckExistence ( ) 1531 { 1532 // check the existence all matrices in all 3 formats 1533 fire_updates (false) ; 1534 for (int id = 1 ; id <= Stats.length ; id++) 1535 { 1536 CheckExistence (id) ; 1537 } 1538 fire_updates (true) ; 1539 } 1540 CheckExistence(int id)1541 private boolean [ ] CheckExistence (int id) 1542 { 1543 // check the existence of a single file (in all 3 formats) 1544 boolean [ ] exists = new boolean [4] ; 1545 boolean [ ] etable = new boolean [3] ; 1546 1547 String Group = (String) Stats [id-1][1] ; 1548 String Name = (String) Stats [id-1][2] ; 1549 1550 for (int j = 0 ; j < 3 ; j++) 1551 { 1552 etable [j] = (((String) get_table_value (id, j+1)).charAt (0) == 'x') ; 1553 } 1554 1555 for (int j = 0 ; j < 4 ; j++) 1556 { 1557 exists [j] = false ; 1558 } 1559 1560 // check for mat/HB/west0067.mat 1561 File G = new File (mat, Group) ; 1562 if (G.isDirectory ( ) && (new File (G, Name + ".mat")).exists ( )) 1563 { 1564 exists [0] = true ; 1565 } 1566 1567 // check for MM/HB/west0067.tar.gz 1568 G = new File (MM, Group) ; 1569 if (G.isDirectory ( ) && (new File (G, Name + ".tar.gz")).exists ( )) 1570 { 1571 exists [1] = true ; 1572 } 1573 1574 // check for MM/HB/west0067.tar.gz 1575 G = new File (RB, Group) ; 1576 if (G.isDirectory ( ) && (new File (G, Name + ".tar.gz")).exists ( )) 1577 { 1578 exists [2] = true ; 1579 } 1580 1581 // check for files/HB/west0067.png 1582 G = new File (iconDir, Group) ; 1583 if (G.isDirectory ( ) && (new File (G, Name + ".png")).exists ( )) 1584 { 1585 exists [3] = true ; 1586 } 1587 1588 // update the matrix table (mat, MM, and RB columns) 1589 for (int j = 0 ; j < 3 ; j++) 1590 { 1591 if (etable [j] != exists [j]) 1592 { 1593 // only update the table if the existence status has changed 1594 set_table_value (exists [j] ? "x" : "-", id, j+1) ; 1595 } 1596 } 1597 return (exists) ; 1598 } 1599 1600 //------------------------------------------------------------------------- 1601 // get long from JTextField 1602 //------------------------------------------------------------------------- 1603 getLong(JTextField tfield, long Default)1604 private long getLong (JTextField tfield, long Default) 1605 { 1606 String s = tfield.getText ( ) ; 1607 long result = Default ; 1608 if (s.length ( ) > 0) 1609 { 1610 try 1611 { 1612 result = Long.parseLong (s) ; 1613 } 1614 catch (Exception e) 1615 { 1616 } 1617 } 1618 return (result) ; 1619 } 1620 1621 //------------------------------------------------------------------------- 1622 // get double from JTextField 1623 //------------------------------------------------------------------------- 1624 getDouble(JTextField tfield, double Default)1625 private double getDouble (JTextField tfield, double Default) 1626 { 1627 String s = tfield.getText ( ) ; 1628 double result = Default ; 1629 if (s.length ( ) > 0) 1630 { 1631 try 1632 { 1633 result = Double.parseDouble (s) ; 1634 } 1635 catch (Exception e) 1636 { 1637 } 1638 } 1639 return (result) ; 1640 } 1641 1642 //------------------------------------------------------------------------- 1643 // change to a wait cursor 1644 //------------------------------------------------------------------------- 1645 please_wait( )1646 private void please_wait ( ) 1647 { 1648 this.setCursor (Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR)) ; 1649 } 1650 1651 //------------------------------------------------------------------------- 1652 // change to a normal cursor 1653 //------------------------------------------------------------------------- 1654 the_long_wait_is_over( )1655 private void the_long_wait_is_over ( ) 1656 { 1657 this.setCursor (Cursor.getDefaultCursor ( )) ; 1658 } 1659 1660 //------------------------------------------------------------------------- 1661 // make or clear a selection 1662 //------------------------------------------------------------------------- 1663 make_selection(boolean action)1664 private void make_selection (boolean action) 1665 { 1666 // set selections according to controls 1667 please_wait ( ) ; 1668 fire_updates (false) ; 1669 1670 long minrow = getLong (minrow_Field, 0) ; 1671 long maxrow = getLong (maxrow_Field, INF) ; 1672 1673 long mincol = getLong (mincol_Field, 0) ; 1674 long maxcol = getLong (maxcol_Field, INF) ; 1675 1676 long minnentries = getLong (minnentries_Field, 0) ; 1677 long maxnentries = getLong (maxnentries_Field, INF) ; 1678 1679 double minpsym = getDouble (minpsym_Field, 0) ; 1680 double maxpsym = getDouble (maxpsym_Field, 1.0) ; 1681 1682 double minnsym = getDouble (minnsym_Field, 0) ; 1683 double maxnsym = getDouble (maxnsym_Field, 1.0) ; 1684 1685 boolean shape_square = shape_square_Button.isSelected ( ) ; 1686 boolean shape_rect = shape_rect_Button.isSelected ( ) ; 1687 boolean shape_either = shape_either_Button.isSelected ( ) ; 1688 1689 boolean posdef_yes = posdef_yes_Button.isSelected ( ) ; 1690 boolean posdef_no = posdef_no_Button.isSelected ( ) ; 1691 boolean posdef_either = posdef_either_Button.isSelected ( ) ; 1692 1693 boolean nd_yes = nd_yes_Button.isSelected ( ) ; 1694 boolean nd_no = nd_no_Button.isSelected ( ) ; 1695 boolean nd_either = nd_either_Button.isSelected ( ) ; 1696 1697 boolean real_yes = real_yes_Button.isSelected ( ) ; 1698 boolean real_no = real_no_Button.isSelected ( ) ; 1699 boolean real_either = real_either_Button.isSelected ( ) ; 1700 1701 // create HashSet for the selected groups 1702 Set<String> Gset = null ; 1703 Object [ ] Gsel = Group_List.getSelectedValuesList ( ).toArray ( ) ; 1704 int ngroups = Gsel.length ; 1705 if (ngroups > 0) 1706 { 1707 for (int i = 0 ; i < ngroups ; i++) 1708 { 1709 if (((String) Gsel [i]).equals (all_groups)) ngroups = 0 ; 1710 } 1711 Gset = new HashSet<String> ( ) ; 1712 for (int i = 0 ; i < ngroups ; i++) 1713 { 1714 Gset.add ((String) Gsel [i]) ; 1715 if (debug) System.out.println ("Group: " + (String) Gsel [i]) ; 1716 } 1717 } 1718 1719 // create HashSet for the selected kinds 1720 Set<String> Kset = null ; 1721 Object [ ] Ksel = Kind_List.getSelectedValuesList ( ).toArray ( ) ; 1722 int nkinds = Ksel.length ; 1723 if (nkinds > 0) 1724 { 1725 for (int i = 0 ; i < nkinds ; i++) 1726 { 1727 if (((String) Ksel [i]).equals (all_kinds)) nkinds = 0 ; 1728 } 1729 Kset = new HashSet<String> ( ) ; 1730 for (int i = 0 ; i < nkinds ; i++) 1731 { 1732 Kset.add ((String) Ksel [i]) ; 1733 if (debug) System.out.println ("Kind: " + ((String) Ksel [i])) ; 1734 } 1735 } 1736 1737 for (int id = 1 ; id <= Stats.length ; id++) 1738 { 1739 1740 // look at the matrix properties to see if it fits the selection 1741 long nrows = (Long) Stats [id-1][3] ; 1742 long ncols = (Long) Stats [id-1][4] ; 1743 long nentries = (Long) Stats [id-1][5] ; 1744 1745 int isReal = (Integer) Stats [id-1][6] ; 1746 int isBinary = (Integer) Stats [id-1][7] ; 1747 int isND = (Integer) Stats [id-1][8] ; 1748 int posdef = (Integer) Stats [id-1][9] ; 1749 1750 double psym = (Double) Stats [id-1][10] ; 1751 double nsym = (Double) Stats [id-1][11] ; 1752 1753 boolean choose_group = true ; 1754 if (ngroups > 0) 1755 { 1756 String group = (String) Stats [id-1][1] ; 1757 choose_group = Gset.contains (group) ; 1758 } 1759 1760 boolean choose_kind = true ; 1761 if (nkinds > 0) 1762 { 1763 String kind = SimplifyKind ((String) Stats [id-1][12]) ; 1764 choose_kind = Kset.contains (kind) ; 1765 } 1766 1767 if ((minrow <= nrows && nrows <= maxrow) && 1768 (mincol <= ncols && ncols <= maxcol) && 1769 (minnentries <= nentries && nentries <= maxnentries) && 1770 (minpsym <= psym && psym <= maxpsym) && 1771 (minnsym <= nsym && nsym <= maxnsym) && 1772 (posdef_either || 1773 (posdef_yes && posdef == 1) || 1774 (posdef_no && posdef == 0)) && 1775 (nd_either || 1776 (nd_yes && isND == 1) || 1777 (nd_no && isND == 0)) && 1778 (real_either || 1779 (real_yes && isReal == 1) || 1780 (real_no && isReal == 0)) && 1781 (shape_either || 1782 (shape_square && nrows == ncols) || 1783 (shape_rect && nrows != ncols)) && 1784 choose_group && choose_kind) 1785 { 1786 // change the selection box for this matrix id 1787 set_table_value (action, id, 0) ; 1788 } 1789 } 1790 fire_updates (true) ; 1791 progress1_Bar.setValue (0) ; 1792 progress2_Bar.setValue (0) ; 1793 the_long_wait_is_over ( ) ; 1794 } 1795 1796 //------------------------------------------------------------------------- 1797 // reset button 1798 //------------------------------------------------------------------------- 1799 reset_Button_action(ActionEvent e)1800 private void reset_Button_action (ActionEvent e) 1801 { 1802 // reset the selection criteria to the defaults 1803 minrow_Field.setText ("") ; 1804 maxrow_Field.setText ("") ; 1805 1806 mincol_Field.setText ("") ; 1807 maxcol_Field.setText ("") ; 1808 1809 minnentries_Field.setText ("") ; 1810 maxnentries_Field.setText ("") ; 1811 1812 minpsym_Field.setText ("0.0") ; 1813 maxpsym_Field.setText ("1.0") ; 1814 1815 minnsym_Field.setText ("0.0") ; 1816 maxnsym_Field.setText ("1.0") ; 1817 1818 shape_either_Button.setSelected (true) ; 1819 posdef_either_Button.setSelected (true) ; 1820 nd_either_Button.setSelected (true) ; 1821 real_either_Button.setSelected (true) ; 1822 1823 Group_List.clearSelection ( ) ; 1824 Kind_List.clearSelection ( ) ; 1825 1826 progress1_Bar.setValue (0) ; 1827 progress2_Bar.setValue (0) ; 1828 } 1829 1830 //------------------------------------------------------------------------- 1831 // clear button 1832 //------------------------------------------------------------------------- 1833 clear_Button_action(ActionEvent e)1834 private void clear_Button_action (ActionEvent e) 1835 { 1836 // set selections according to controls 1837 please_wait ( ) ; 1838 fire_updates (false) ; 1839 1840 for (int id = 1 ; id <= Stats.length ; id++) 1841 { 1842 // clear the selection box for this matrix id 1843 set_table_value (false, id, 0) ; 1844 } 1845 fire_updates (true) ; 1846 progress1_Bar.setValue (0) ; 1847 progress2_Bar.setValue (0) ; 1848 the_long_wait_is_over ( ) ; 1849 } 1850 1851 //------------------------------------------------------------------------- 1852 // select popup menu item 1853 //------------------------------------------------------------------------- 1854 popup_action(ActionEvent e, boolean action)1855 private void popup_action (ActionEvent e, boolean action) 1856 { 1857 // select or deselect the highlight matrices 1858 please_wait ( ) ; 1859 int [ ] highlighted = get_highlighted_ids ( ) ; 1860 int n = highlighted.length ; 1861 for (int k = 0 ; k < n ; k++) 1862 { 1863 set_table_value (action, highlighted [k], 0) ; 1864 } 1865 the_long_wait_is_over ( ) ; 1866 } 1867 1868 //------------------------------------------------------------------------- 1869 // export popup menu item 1870 //------------------------------------------------------------------------- 1871 export_list_action(ActionEvent e, boolean csv)1872 private void export_list_action (ActionEvent e, boolean csv) 1873 { 1874 // export the list in the order of the current view 1875 if (chooser.showSaveDialog (ssgui.this) == JFileChooser.APPROVE_OPTION) 1876 { 1877 please_wait ( ) ; 1878 print_out = null ; 1879 try 1880 { 1881 print_out = new PrintWriter (chooser.getSelectedFile ( )) ; 1882 int [ ] ids = get_download_ids ( ) ; 1883 int n = ids.length ; 1884 1885 // print the header 1886 if (csv) 1887 { 1888 print_out.println ("mat, MM, RB, id, Group, Name, rows, " + 1889 "cols, entries, real, binary, 2D/3D, posdef, psym, " + 1890 "nsym, kind") ; 1891 } 1892 else 1893 { 1894 print_out.println ("%% Matrices selected from ssgui:") ; 1895 print_out.println ("% Example usage:") ; 1896 print_out.println ("% for k = 1:length(ids)") ; 1897 print_out.println ("% Problem = ssget (ids (k))") ; 1898 print_out.println ("% end") ; 1899 print_out.println ("ids = [") ; 1900 } 1901 1902 for (int k = 0 ; k < n ; k++) 1903 { 1904 // get the matrix id and stats 1905 int id = ids [k] ; 1906 boolean [ ] exists = CheckExistence (id) ; 1907 String Group = (String) Stats [id-1][1] ; 1908 String Name = (String) Stats [id-1][2] ; 1909 long nrows = (Long) Stats [id-1][3] ; 1910 long ncols = (Long) Stats [id-1][4] ; 1911 long nentries = (Long) Stats [id-1][5] ; 1912 int isReal = (Integer) Stats [id-1][6] ; 1913 int isBinary = (Integer) Stats [id-1][7] ; 1914 int isND = (Integer) Stats [id-1][8] ; 1915 int posdef = (Integer) Stats [id-1][9] ; 1916 double psym = (Double) Stats [id-1][10] ; 1917 double nsym = (Double) Stats [id-1][11] ; 1918 String kind = (String) Stats [id-1][12] ; 1919 1920 if (csv) 1921 { 1922 // print the matrix stats in a single CSV line of text 1923 print_out.println ( 1924 exists [0] + ", " + exists [1] + ", " + 1925 exists [2] + ", " + id + ", " + Group + ", " + 1926 Name + ", " + nrows + ", " + ncols + ", " + 1927 nentries + ", " + isReal + ", " + isBinary + ", " + 1928 isND + ", " + posdef + ", " + psym + ", " + 1929 nsym + ", " + kind) ; 1930 } 1931 else 1932 { 1933 // print the matrix id, with a comment for the name 1934 print_out.println (id + " % " + Group + "/" + Name) ; 1935 } 1936 } 1937 if (!csv) 1938 { 1939 print_out.println ("] ;") ; 1940 } 1941 } 1942 catch (Exception err) 1943 { 1944 // display warning dialog 1945 JOptionPane.showMessageDialog (this, "Export failed.", 1946 "Warning", JOptionPane.WARNING_MESSAGE) ; 1947 } 1948 finally 1949 { 1950 close_printer_stream (print_out) ; 1951 } 1952 the_long_wait_is_over ( ) ; 1953 } 1954 } 1955 1956 //------------------------------------------------------------------------- 1957 // help button 1958 //------------------------------------------------------------------------- 1959 help_Button_action(ActionEvent e)1960 private void help_Button_action (ActionEvent e) 1961 { 1962 // create the Help window 1963 please_wait ( ) ; 1964 JFrame help_Frame = new JFrame ("Help: SuiteSparse Matrix Collection") ; 1965 1966 // open the HTML help file and put it in an editor pane 1967 JEditorPane editorPane = new JEditorPane ( ) ; 1968 editorPane.setEditable (false) ; 1969 URL helpURL = ssgui.class.getResource ("sshelp.html") ; 1970 if (helpURL != null) 1971 { 1972 try 1973 { 1974 editorPane.setPage (helpURL) ; 1975 } 1976 catch (IOException error) 1977 { 1978 // display warning dialog 1979 JOptionPane.showMessageDialog (this, 1980 "Sorry, Help document sshelp.html not found.", 1981 "Warning", JOptionPane.WARNING_MESSAGE) ; 1982 } 1983 } 1984 1985 // Put the editor pane in a scroll pane. 1986 JScrollPane editorScrollPane = new JScrollPane (editorPane) ; 1987 1988 // Add the scroll pane to the Help window 1989 help_Frame.getContentPane ( ).add (editorScrollPane) ; 1990 help_Frame.setSize (800,600) ; 1991 help_Frame.setVisible (true) ; 1992 1993 the_long_wait_is_over ( ) ; 1994 } 1995 1996 //------------------------------------------------------------------------- 1997 // get the icon filename 1998 //------------------------------------------------------------------------- 1999 icon_file(String fullname)2000 private String icon_file (String fullname) 2001 { 2002 return ("files/" + fullname + ".png") ; 2003 } 2004 2005 //------------------------------------------------------------------------- 2006 // update the icon 2007 //------------------------------------------------------------------------- 2008 update_icon(String fullname)2009 private void update_icon (String fullname) 2010 { 2011 // fullname is of the form Group/Name (HB/west0479, for example) 2012 icon_Label.setText (fullname) ; 2013 ImageIcon icon = new ImageIcon (fix_name (icon_file (fullname))) ; 2014 if (icon.getIconWidth ( ) < 0) 2015 { 2016 // icon image failed to load; get the image from the web 2017 icon = new ImageIcon (get_url (sssite +"/"+ icon_file (fullname))) ; 2018 } 2019 icon_Label.setIcon (icon) ; 2020 } 2021 2022 //-------------------------------------------------------------------------- 2023 // cancel button 2024 //-------------------------------------------------------------------------- 2025 cancel_Button_action(ActionEvent e)2026 private void cancel_Button_action (ActionEvent e) 2027 { 2028 if (downloading && !cancel) 2029 { 2030 cancel = true ; 2031 cancel_Button.setEnabled (false) ; 2032 cancel_Button.setToolTipText ("canceling...") ; 2033 } 2034 } 2035 2036 //------------------------------------------------------------------------- 2037 // get all icons 2038 //------------------------------------------------------------------------- 2039 get_all_icons( )2040 private void get_all_icons ( ) 2041 { 2042 // get all icons 2043 start_download_thread (0) ; 2044 } 2045 2046 //------------------------------------------------------------------------- 2047 // download button 2048 //------------------------------------------------------------------------- 2049 download_Button_action(ActionEvent e)2050 private void download_Button_action (ActionEvent e) 2051 { 2052 // get the selected matrices 2053 start_download_thread (2) ; 2054 } 2055 2056 //------------------------------------------------------------------------- 2057 // start the downloader thread 2058 //------------------------------------------------------------------------- 2059 start_download_thread(int what)2060 private void start_download_thread (int what) 2061 { 2062 if (!downloading) 2063 { 2064 // only allow one active download at a time 2065 downloading = true ; 2066 cancel = false ; 2067 2068 if (gui_ready) 2069 { 2070 cancel_Button.setEnabled (true) ; 2071 cancel_Button.setToolTipText 2072 ("Click to cancel the current download.") ; 2073 } 2074 2075 if (what == 0) 2076 { 2077 // get all the icons 2078 get_icons = true ; 2079 download_ids = null ; 2080 } 2081 else 2082 { 2083 // download one or more matrices 2084 get_icons = false ; 2085 download_ids = get_download_ids ( ) ; 2086 } 2087 set_selected_label (false) ; 2088 // start the downloader thread 2089 ssdownload tt = new ssdownload ( ) ; 2090 } 2091 } 2092 2093 //-------------------------------------------------------------------------- 2094 // downloader thread 2095 //-------------------------------------------------------------------------- 2096 2097 private class ssdownload implements Runnable 2098 { 2099 2100 // constructor starts the downloader thread ssdownload( )2101 public ssdownload ( ) 2102 { 2103 Thread thread = new Thread (this) ; 2104 thread.start ( ) ; 2105 } 2106 2107 // thread.start calls the run method run( )2108 public void run ( ) 2109 { 2110 2111 if (get_icons) 2112 { 2113 // get all missing icons 2114 progress1_Bar.setValue (1) ; 2115 progress1_Bar.setMaximum (Stats.length) ; 2116 icon_Label.setBorder (BorderFactory.createTitledBorder 2117 ("checking for new matrix icons")) ; 2118 for (int id = 1 ; !cancel && id <= Stats.length ; id++) 2119 { 2120 boolean [ ] exists = CheckExistence (id) ; 2121 if (!exists [3]) 2122 { 2123 icon_Label.setBorder (BorderFactory.createTitledBorder 2124 ("downloading new matrix icons")) ; 2125 String Group = (String) Stats [id-1][1] ; 2126 String Name = (String) Stats [id-1][2] ; 2127 String fullname = Group + "/" + Name ; 2128 CheckDir ("files/" + Group) ; 2129 download_file (icon_file (fullname)) ; 2130 update_icon (fullname) ; 2131 } 2132 progress1_Bar.setValue (id+2) ; 2133 } 2134 progress1_Bar.setValue (Stats.length) ; 2135 icon_Label.setBorder (BorderFactory.createTitledBorder 2136 ("matrix icon")) ; 2137 } 2138 2139 if (download_ids != null && download_ids.length > 0) 2140 { 2141 // download all selected matrices in the requested formats 2142 2143 // determine which formats to download 2144 int barmax = download_ids.length + 2 ; 2145 2146 boolean format_mat = format_mat_Button.isSelected ( ) ; 2147 boolean format_mm = format_mm_Button.isSelected ( ) ; 2148 boolean format_rb = format_rb_Button.isSelected ( ) ; 2149 2150 // start the overall progress bar 2151 progress1_Bar.setValue (1) ; 2152 progress1_Bar.setMaximum (barmax) ; 2153 2154 // download all the files 2155 for (int k = 0 ; !cancel && k < download_ids.length ; k++) 2156 { 2157 int id = download_ids [k] ; 2158 2159 // get matrxx 2160 String Group = (String) Stats [id-1][1] ; 2161 String Name = (String) Stats [id-1][2] ; 2162 String fullname = Group + "/" + Name ; 2163 2164 // recheck to see if the matrix exists in the 4 formats 2165 boolean [ ] exists = CheckExistence (id) ; 2166 2167 if (!exists [3]) 2168 { 2169 // always download the matrix icon if it doesn't exist 2170 CheckDir ("files/" + Group) ; 2171 download_file (icon_file (fullname)) ; 2172 update_icon (fullname) ; 2173 } 2174 2175 if (!exists [0] && format_mat) 2176 { 2177 // download the matrix in MATLAB format 2178 update_icon (fullname) ; 2179 CheckDir ("mat/" + Group) ; 2180 download_file ("mat/" + fullname + ".mat") ; 2181 } 2182 2183 if (!exists [1] && format_mm) 2184 { 2185 // download the matrix in Matrix Market format 2186 update_icon (fullname) ; 2187 CheckDir ("MM/" + Group) ; 2188 download_file ("MM/" + fullname + ".tar.gz") ; 2189 } 2190 2191 if (!exists [2] && format_rb) 2192 { 2193 // download the matrix in Rutherford/Boeing format 2194 update_icon (fullname) ; 2195 CheckDir ("RB/" + Group) ; 2196 download_file ("RB/" + fullname + ".tar.gz") ; 2197 } 2198 2199 progress1_Bar.setValue (k+2) ; 2200 } 2201 2202 // update the mat/MM/RB check boxes 2203 for (int k = 0 ; k < download_ids.length ; k++) 2204 { 2205 int id = download_ids [k] ; 2206 CheckExistence (id) ; 2207 } 2208 2209 // finish the overall progress bar 2210 progress1_Bar.setValue (barmax) ; 2211 } 2212 2213 cancel_Button.setEnabled (false) ; 2214 cancel_Button.setToolTipText ("No downloads in progress.") ; 2215 2216 set_selected_label (true) ; 2217 cancel = false ; 2218 downloading = false ; 2219 } 2220 } 2221 2222 //-------------------------------------------------------------------------- 2223 // get a URL 2224 //-------------------------------------------------------------------------- 2225 get_url(String urlstring)2226 private URL get_url (String urlstring) 2227 { 2228 try 2229 { 2230 return (new URL (urlstring)) ; 2231 } 2232 catch (MalformedURLException e) 2233 { 2234 // display warning dialog 2235 JOptionPane.showMessageDialog (this, "Invalid URL: " 2236 + urlstring, "Warning", JOptionPane.WARNING_MESSAGE) ; 2237 return (null) ; 2238 } 2239 } 2240 2241 //-------------------------------------------------------------------------- 2242 // download a file 2243 //-------------------------------------------------------------------------- 2244 download_file(String filename)2245 private void download_file (String filename) 2246 { 2247 boolean ok = true ; 2248 if (cancel) return ; 2249 String urlstring = sssite + "/" + filename ; 2250 if (debug) System.out.println ("downloading: " + urlstring) ; 2251 2252 // create the URL 2253 URL url = get_url (urlstring) ; 2254 if (url == null) return ; 2255 2256 // download the file 2257 url_in = null ; 2258 ftemp_out = null ; 2259 ftemp_name = filename + "_IN_PROGREss" ; 2260 int barmax = 1 ; 2261 2262 try 2263 { 2264 // Follow redirects manually 2265 int max_redirects = 5; 2266 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 2267 2268 for(int redirect_count = 0; redirect_count < max_redirects; redirect_count++) 2269 { 2270 int status = conn.getResponseCode(); 2271 if (status >= 300 && status <= 308) 2272 { 2273 // Redirecting 2274 String loc = conn.getHeaderField("Location"); 2275 url = new URL(loc); 2276 conn = (HttpURLConnection) url.openConnection(); 2277 } 2278 else 2279 { 2280 break; 2281 } 2282 } 2283 2284 // determine the file size (fails for files > 2GB) 2285 int len = conn.getContentLength(); 2286 2287 // start the progress bar 2288 if (gui_ready) 2289 { 2290 if (len < 0) 2291 { 2292 progress2_Bar.setIndeterminate (true) ; 2293 progress_size_Label.setText ("") ; 2294 } 2295 else 2296 { 2297 progress2_Bar.setValue (0) ; 2298 // display the filesize to the right of the progress bar 2299 if (len < M) 2300 { 2301 barmax = 1 + len / K ; 2302 progress_size_Label.setText (((len+K/2) / K) + " KB") ; 2303 } 2304 else 2305 { 2306 barmax = 1 + len / M ; 2307 progress_size_Label.setText (((len+M/2) / M) + " MB") ; 2308 } 2309 } 2310 progress2_Bar.setMaximum (barmax) ; 2311 } 2312 2313 // open the source and destination files 2314 //url_in = new BufferedInputStream (url.openStream ( )) ; 2315 url_in = new BufferedInputStream (conn.getInputStream()) ; 2316 ftemp_out = new BufferedOutputStream (new FileOutputStream 2317 (fix_name (ftemp_name)), buffersize) ; 2318 2319 // transfer the data 2320 byte buffer [ ] = new byte [buffersize] ; 2321 long bytes_read = 0 ; 2322 int count = 0 ; 2323 while (!cancel && (count = url_in.read (buffer, 0, buffersize)) >= 0) 2324 { 2325 if (ftemp_out != null) ftemp_out.write (buffer, 0, count) ; 2326 bytes_read += count ; 2327 if (gui_ready && len > 0) 2328 { 2329 if (len < M) 2330 { 2331 progress2_Bar.setValue ((int) (bytes_read / K)) ; 2332 } 2333 else 2334 { 2335 progress2_Bar.setValue ((int) (bytes_read / M)) ; 2336 } 2337 } 2338 } 2339 } 2340 catch (Exception e) 2341 { 2342 if (debug) 2343 { 2344 System.out.println("Download failed: " + urlstring); 2345 } 2346 ok = false ; 2347 } 2348 2349 if (gui_ready) 2350 { 2351 progress2_Bar.setIndeterminate (false) ; 2352 progress2_Bar.setValue (barmax) ; 2353 progress_size_Label.setText ("") ; 2354 } 2355 2356 // wrap-up 2357 if (ok && !cancel) 2358 { 2359 // success: rename the temp file to the permanent filename 2360 cleanup (false) ; 2361 File fsrc = new File (fix_name (ftemp_name)) ; 2362 File fdst = new File (fix_name (filename)) ; 2363 fsrc.renameTo (fdst) ; 2364 } 2365 else 2366 { 2367 // cancelled, or something failed: delete the files if they exist 2368 cleanup (true) ; 2369 } 2370 } 2371 2372 //-------------------------------------------------------------------------- 2373 // download the latest matrix stats 2374 //-------------------------------------------------------------------------- 2375 download_matrix_stats( )2376 private Object [ ][ ] download_matrix_stats ( ) 2377 { 2378 download_file (ssindex) ; // download files/ss_index.mat 2379 download_file (ssstats) ; // download files/ssstats.csv 2380 return (load_ssstats ( )) ; // load the ssstats.csv file 2381 } 2382 2383 //-------------------------------------------------------------------------- 2384 // prepend the ss rchive directory and replace '/' with the file separator 2385 //-------------------------------------------------------------------------- 2386 fix_name(String s)2387 private static String fix_name (String s) 2388 { 2389 // file separator is '/' on Unix/Solaris/Linux/Mac, and '\' on Windows 2390 String r = ssarchive ; 2391 if (s != null) 2392 { 2393 r = r + s ; 2394 } 2395 return (r.replace ('/', File.separatorChar)) ; 2396 } 2397 2398 //-------------------------------------------------------------------------- 2399 // close an output stream 2400 //-------------------------------------------------------------------------- 2401 close_output(OutputStream out)2402 private static void close_output (OutputStream out) 2403 { 2404 try 2405 { 2406 if (out != null) out.close ( ) ; 2407 } 2408 catch (IOException e) 2409 { 2410 } 2411 } 2412 2413 //-------------------------------------------------------------------------- 2414 // close an input stream 2415 //-------------------------------------------------------------------------- 2416 close_reader(Reader in)2417 private static void close_reader (Reader in) 2418 { 2419 try 2420 { 2421 if (in != null) in.close ( ) ; 2422 } 2423 catch (IOException e) 2424 { 2425 } 2426 } 2427 2428 //-------------------------------------------------------------------------- 2429 // close a printer stream 2430 //-------------------------------------------------------------------------- 2431 close_printer_stream(PrintWriter out)2432 private static void close_printer_stream (PrintWriter out) 2433 { 2434 if (out != null) out.close ( ) ; 2435 } 2436 2437 //-------------------------------------------------------------------------- 2438 // delete a file 2439 //-------------------------------------------------------------------------- 2440 delete_file(String filename)2441 private static void delete_file (String filename) 2442 { 2443 if (filename != null) 2444 { 2445 File ff = new File (fix_name (filename)) ; 2446 if (ff.exists ( )) ff.delete ( ) ; 2447 } 2448 } 2449 2450 //-------------------------------------------------------------------------- 2451 // cleanup 2452 //-------------------------------------------------------------------------- 2453 cleanup(boolean delete)2454 private static void cleanup (boolean delete) 2455 { 2456 // close input streams, if any 2457 try 2458 { 2459 if (url_in != null) url_in.close ( ) ; 2460 } 2461 catch (IOException e) 2462 { 2463 } 2464 url_in = null ; 2465 2466 // close temporary file 2467 close_output (ftemp_out) ; 2468 ftemp_out = null ; 2469 2470 if (delete) 2471 { 2472 // delete temporary file 2473 delete_file (ftemp_name) ; 2474 ftemp_name = null ; 2475 } 2476 2477 // close the printer stream, if any 2478 close_printer_stream (print_out) ; 2479 2480 // close the reader stream, if any 2481 close_reader (in_reader) ; 2482 } 2483 2484 //-------------------------------------------------------------------------- 2485 // main method 2486 //-------------------------------------------------------------------------- 2487 main(String args [ ])2488 public static void main (String args [ ]) 2489 { 2490 // register a shutdown hook 2491 Runtime.getRuntime ( ).addShutdownHook 2492 ( 2493 new Thread ( ) 2494 { 2495 public void run ( ) 2496 { 2497 // delete any temporary files when the ssgui shuts down, 2498 // and close any files 2499 cleanup (true) ; 2500 } 2501 } 2502 ) ; 2503 2504 // start the GUI in its own thread 2505 EventQueue.invokeLater 2506 ( 2507 new Runnable ( ) 2508 { 2509 public void run ( ) 2510 { 2511 new ssgui ( ).setVisible (true) ; 2512 } 2513 } 2514 ) ; 2515 } 2516 } 2517