123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- /*
- * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include "ClassViewWidget.h"
- #include "HackStudio.h"
- #include "ProjectDeclarations.h"
- #include <AK/StdLibExtras.h>
- #include <LibGUI/BoxLayout.h>
- #include <string.h>
- namespace HackStudio {
- ClassViewWidget::ClassViewWidget()
- {
- set_layout<GUI::VerticalBoxLayout>();
- m_class_tree = add<GUI::TreeView>();
- m_class_tree->on_selection_change = [this] {
- const auto& index = m_class_tree->selection().first();
- if (!index.is_valid())
- return;
- auto* node = static_cast<const ClassViewNode*>(index.internal_data());
- if (!node->declaration)
- return;
- open_file(node->declaration->position.file, node->declaration->position.line, node->declaration->position.column);
- };
- }
- RefPtr<ClassViewModel> ClassViewModel::create()
- {
- return adopt_ref(*new ClassViewModel());
- }
- int ClassViewModel::row_count(const GUI::ModelIndex& index) const
- {
- if (!index.is_valid())
- return m_root_scope.size();
- auto* node = static_cast<ClassViewNode*>(index.internal_data());
- return node->children.size();
- }
- GUI::Variant ClassViewModel::data(const GUI::ModelIndex& index, GUI::ModelRole role) const
- {
- auto* node = static_cast<ClassViewNode const*>(index.internal_data());
- switch (role) {
- case GUI::ModelRole::Display: {
- return node->name;
- }
- case GUI::ModelRole::Icon: {
- if (!node->declaration)
- return {};
- auto icon = ProjectDeclarations::get_icon_for(node->declaration->type);
- if (icon.has_value())
- return icon.value();
- return {};
- }
- default:
- return {};
- }
- }
- GUI::ModelIndex ClassViewModel::parent_index(const GUI::ModelIndex& index) const
- {
- if (!index.is_valid())
- return {};
- auto* child = static_cast<ClassViewNode const*>(index.internal_data());
- auto* parent = child->parent;
- if (parent == nullptr)
- return {};
- if (parent->parent == nullptr) {
- for (size_t row = 0; row < m_root_scope.size(); row++) {
- if (m_root_scope.ptr_at(row).ptr() == parent)
- return create_index(row, 0, parent);
- }
- VERIFY_NOT_REACHED();
- }
- for (size_t row = 0; row < parent->parent->children.size(); row++) {
- ClassViewNode* child_at_row = parent->parent->children.ptr_at(row).ptr();
- if (child_at_row == parent)
- return create_index(row, 0, parent);
- }
- VERIFY_NOT_REACHED();
- }
- GUI::ModelIndex ClassViewModel::index(int row, int column, const GUI::ModelIndex& parent_index) const
- {
- if (!parent_index.is_valid())
- return create_index(row, column, &m_root_scope[row]);
- auto* parent = static_cast<ClassViewNode const*>(parent_index.internal_data());
- auto* child = &parent->children[row];
- return create_index(row, column, child);
- }
- ClassViewModel::ClassViewModel()
- {
- m_root_scope.clear();
- ProjectDeclarations::the().for_each_declared_symbol([this](auto& decl) {
- if (decl.type == CodeComprehension::DeclarationType::Class
- || decl.type == CodeComprehension::DeclarationType::Struct
- || decl.type == CodeComprehension::DeclarationType::Member
- || decl.type == CodeComprehension::DeclarationType::Namespace) {
- add_declaration(decl);
- }
- });
- }
- static ClassViewNode& add_child_node(NonnullOwnPtrVector<ClassViewNode>& children, NonnullOwnPtr<ClassViewNode>&& node_ptr, ClassViewNode* parent, CodeComprehension::Declaration const* declaration)
- {
- node_ptr->parent = parent;
- node_ptr->declaration = declaration;
- size_t inserted_index = 0;
- ClassViewNode& node = *node_ptr;
- // Insert into parent's children list, sorted lexicographically by name.
- children.insert_before_matching(
- move(node_ptr), [&node](auto& other_node) {
- return strncmp(node.name.characters_without_null_termination(), other_node->name.characters_without_null_termination(), min(node.name.length(), other_node->name.length())) < 0;
- },
- 0, &inserted_index);
- return children.at(inserted_index);
- }
- void ClassViewModel::add_declaration(CodeComprehension::Declaration const& decl)
- {
- ClassViewNode* parent = nullptr;
- auto scope_parts = decl.scope.view().split_view("::");
- if (!scope_parts.is_empty()) {
- // Traverse declarations tree to the parent of 'decl'
- for (auto& node : m_root_scope) {
- if (node.name == scope_parts.first())
- parent = &node;
- }
- if (parent == nullptr) {
- m_root_scope.append(make<ClassViewNode>(scope_parts.first()));
- parent = &m_root_scope.last();
- }
- for (size_t i = 1; i < scope_parts.size(); ++i) {
- auto& scope = scope_parts[i];
- ClassViewNode* next { nullptr };
- for (auto& child : parent->children) {
- if (child.name == scope) {
- next = &child;
- break;
- }
- }
- if (next) {
- parent = next;
- continue;
- }
- parent = &add_child_node(parent->children, make<ClassViewNode>(scope), parent, nullptr);
- }
- }
- NonnullOwnPtrVector<ClassViewNode>* children_of_parent = nullptr;
- if (parent) {
- children_of_parent = &parent->children;
- } else {
- children_of_parent = &m_root_scope;
- }
- bool already_exists = false;
- for (auto& child : *children_of_parent) {
- if (child.name == decl.name) {
- already_exists = true;
- if (!child.declaration) {
- child.declaration = &decl;
- }
- break;
- }
- }
- if (!already_exists) {
- add_child_node(*children_of_parent, make<ClassViewNode>(decl.name), parent, &decl);
- }
- }
- void ClassViewWidget::refresh()
- {
- m_class_tree->set_model(ClassViewModel::create());
- }
- }
|