| | 134 | _objectViewsTabControl = TabControl() |
| | 135 | _objectViewsTabControl.dock = DockStyle.Fill |
| | 136 | _objectViewsTabControl.parent = split.panel2 |
| | 137 | |
| | 138 | page = TabPage('Key / Value') |
| | 139 | _objectListView = ListView() |
| | 140 | _objectListView.view = View.Details |
| | 141 | _objectListView.gridLines = true |
| | 142 | _objectListView.fullRowSelect = true |
| | 143 | _objectListView.columns.add('Key') |
| | 144 | _objectListView.columns.add('View') |
| | 145 | _objectListView.dock = DockStyle.Fill |
| | 146 | _objectListView.parent = page |
| | 147 | |
| | 148 | _objectViewsTabControl.tabPages.add(page) |
| | 149 | |
| | 150 | page = TabPage('Property Grid') |
| 374 | | |
| | 402 | |
| | 403 | def _populateObjectListView(obj as Object?) |
| | 404 | listView = _objectListView |
| | 405 | listView.beginUpdate |
| | 406 | try |
| | 407 | listView.items.clear |
| | 408 | for info in _keyValuesOf(obj) |
| | 409 | key = info[0] to String |
| | 410 | value = info[1] |
| | 411 | # isGood = info[2] to bool |
| | 412 | item = ListViewItem(key) |
| | 413 | item.subItems.add(CobraCore.toTechString(value)) |
| | 414 | listView.items.add(item) |
| | 415 | |
| | 416 | if obj inherits AssertException |
| | 417 | _addEntryMode = 2 |
| | 418 | try |
| | 419 | obj.extendObjectTable(this) |
| | 420 | finally |
| | 421 | _addEntryMode = 0 |
| | 422 | |
| | 423 | for i in 2, _objectListView.autoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent) |
| | 424 | finally |
| | 425 | listView.endUpdate |
| | 426 | |
| 429 | | propInfos = List<of PropertyInfo>((obj to Object).getType.getProperties) |
| 430 | | propInfos.sort(ref .comparePropInfo) |
| 431 | | for propInfo in propInfos |
| 432 | | if propInfo.name == 'Item' # used for indexing. technically could be named something else, but this works in practice |
| 433 | | continue |
| 434 | | value = nil |
| 435 | | isGood = false |
| 436 | | try |
| 437 | | value = propInfo.getValue(obj, nil) |
| 438 | | isGood = true |
| 439 | | catch exc as Exception |
| 440 | | if exc inherits TargetInvocationException and exc.innerException |
| 441 | | exc = exc.innerException to ! |
| 442 | | value = 'Caught during get: [exc.getType.name]: [exc.message]' |
| 443 | | propName = .cobraMemberNameFor(propInfo.name) |
| 444 | | child = XTreeNode('[propName] == [CobraCore.toTechString(value)]', propName, value) |
| | 480 | for info in _keyValuesOf(obj) |
| | 481 | key = info[0] to String |
| | 482 | value = info[1] |
| | 483 | isGood = info[2] to bool |
| | 484 | child = XTreeNode('[key] == [CobraCore.toTechString(value)]', key, value) |
| 449 | | lb = c'[' |
| 450 | | if obj inherits System.Collections.IList |
| 451 | | for i in obj.count |
| 452 | | value = nil |
| 453 | | isGood = false |
| 454 | | try |
| 455 | | value = obj[i] |
| 456 | | isGood = true |
| 457 | | catch exc as Exception |
| 458 | | value = 'Caught during IList[lb][i]]: [exc.getType.name]: [exc.message]' |
| 459 | | child = XTreeNode('[lb][i]] == [CobraCore.toTechString(value)]', '[lb][i]]', value) |
| 460 | | if isGood |
| 461 | | if not .isPrimitive(value) |
| 462 | | child.nodes.add(XTreeNode.newDummyNode) |
| 463 | | node.nodes.add(child) |
| 464 | | else if obj inherits System.Collections.IDictionary |
| 465 | | keys = System.Collections.ArrayList(obj.keys) |
| 466 | | keys.sort |
| 467 | | for key in keys |
| 468 | | value = nil |
| 469 | | isGood = false |
| 470 | | try |
| 471 | | value = obj[key] |
| 472 | | isGood = true |
| 473 | | catch exc as Exception |
| 474 | | value = 'Caught during IDictionary[lb][key]]: [exc.getType.name]: [exc.message]' |
| 475 | | lb = c'[' |
| 476 | | child = XTreeNode('[lb][CobraCore.toTechString(key)]] == [CobraCore.toTechString(value)]', '[lb][CobraCore.toTechString(key)]]', value) |
| 477 | | if isGood |
| 478 | | if not .isPrimitive(value) |
| 479 | | child.nodes.add(XTreeNode.newDummyNode) |
| 480 | | node.nodes.add(child) |
| 481 | | else if obj inherits AssertException |
| | 489 | if obj inherits AssertException |
| | 498 | |
| | 499 | def _keyValuesOf(obj as dynamic?) as IEnumerable<of List<of dynamic?>> |
| | 500 | """ |
| | 501 | Yields a series of [keyName, value, isGood] for the given object. |
| | 502 | The series includes properties, indexed elements of IList and keyed elements of IDictionary. |
| | 503 | The keyName is a string. The value could be anything including nil. |
| | 504 | When isGood is false, an exception was caught when retrieving the value and consequently the value says 'Caught during...'. |
| | 505 | |
| | 506 | This method can be used to populate a detailed view of the object, a list of subnodes in a treeview, etc. |
| | 507 | |
| | 508 | Does *not* check for AssertException to invoke any of its special methods for displaying subexpressions. |
| | 509 | """ |
| | 510 | if obj is nil, yield break |
| | 511 | yield ['.getType', obj.getType, true] |
| | 512 | yield ['.toTechString', obj, true] |
| | 513 | propInfos = List<of PropertyInfo>((obj to Object).getType.getProperties) |
| | 514 | propInfos.sort(ref .comparePropInfo) |
| | 515 | for propInfo in propInfos |
| | 516 | if propInfo.name == 'Item' # used for indexing. technically could be named something else, but this works in practice |
| | 517 | continue |
| | 518 | value = nil |
| | 519 | isGood = false |
| | 520 | try |
| | 521 | value = propInfo.getValue(obj, nil) |
| | 522 | isGood = true |
| | 523 | catch exc as Exception |
| | 524 | if exc inherits TargetInvocationException and exc.innerException |
| | 525 | exc = exc.innerException to ! |
| | 526 | value = 'Caught during get: [exc.getType.name]: [exc.message]' |
| | 527 | propName = .cobraMemberNameFor(propInfo.name) |
| | 528 | yield [propName, value, isGood] |
| | 529 | lb = c'[' |
| | 530 | if obj inherits System.Collections.IList |
| | 531 | for i in obj.count |
| | 532 | propName = '[lb][i]]' |
| | 533 | value = nil |
| | 534 | isGood = false |
| | 535 | try |
| | 536 | value = obj[i] |
| | 537 | isGood = true |
| | 538 | catch exc as Exception |
| | 539 | value = 'Caught during IList[propName]: [exc.getType.name]: [exc.message]' |
| | 540 | yield [propName, value, isGood] |
| | 541 | else if obj inherits System.Collections.IDictionary |
| | 542 | keys = System.Collections.ArrayList(obj.keys) |
| | 543 | keys.sort |
| | 544 | for dictKey in keys |
| | 545 | propName = '[lb][CobraCore.toTechString(dictKey)]]' |
| | 546 | value = nil |
| | 547 | isGood = false |
| | 548 | try |
| | 549 | value = obj[dictKey] |
| | 550 | isGood = true |
| | 551 | catch exc as Exception |
| | 552 | value = 'Caught during IDictionary[propName]: [exc.getType.name]: [exc.message]' |
| | 553 | lb = c'[' |
| | 554 | yield [propName, value, isGood] |
| 522 | | text = '[key] == [CobraCore.toTechString(value)]' |
| 523 | | node = XTreeNode(text, key, value) |
| 524 | | _nodeStack.peek.nodes.add(node) |
| | 593 | branch _addEntryMode |
| | 594 | on 1 |
| | 595 | text = '[key] == [CobraCore.toTechString(value)]' |
| | 596 | node = XTreeNode(text, key, value) |
| | 597 | _nodeStack.peek.nodes.add(node) |
| | 598 | on 2 |
| | 599 | item = ListViewItem(key) |
| | 600 | item.subItems.add(CobraCore.toTechString(value)) |
| | 601 | _objectListView.items.add(item) |
| | 602 | else |
| | 603 | throw FallThroughException(_addEntryMode) |