first commit
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python Debugger: Current File",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${file}",
|
||||||
|
"console": "integratedTerminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
EXE/GetCoreTempInfo.dll
Normal file
BIN
EXE/VCTemp.exe
Normal file
BIN
GetCoreTempInfo.dll
Normal file
178
LibreHardwareMonitor-0.9.4/.editorconfig
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
# editorconfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Default settings:
|
||||||
|
# A newline ending every file
|
||||||
|
# Use 4 spaces as indentation
|
||||||
|
[*]
|
||||||
|
insert_final_newline = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
end_of_line = lf
|
||||||
|
|
||||||
|
[project.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# C# files
|
||||||
|
[*.{cs,vb}]
|
||||||
|
|
||||||
|
# New line preferences
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
csharp_new_line_between_query_expression_clauses = true
|
||||||
|
|
||||||
|
# Indentation preferences
|
||||||
|
csharp_indent_block_contents = true
|
||||||
|
csharp_indent_braces = false
|
||||||
|
csharp_indent_case_contents = true
|
||||||
|
csharp_indent_case_contents_when_block = true
|
||||||
|
csharp_indent_switch_labels = true
|
||||||
|
csharp_indent_labels = one_less_than_current
|
||||||
|
|
||||||
|
# Modifier preferences
|
||||||
|
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
|
||||||
|
|
||||||
|
# avoid this. unless absolutely necessary
|
||||||
|
dotnet_style_qualification_for_field = false:suggestion
|
||||||
|
dotnet_style_qualification_for_property = false:suggestion
|
||||||
|
dotnet_style_qualification_for_method = false:suggestion
|
||||||
|
dotnet_style_qualification_for_event = false:suggestion
|
||||||
|
|
||||||
|
# Types: use keywords instead of BCL types, and permit var only when the type is clear
|
||||||
|
csharp_style_var_for_built_in_types = false:suggestion
|
||||||
|
csharp_style_var_when_type_is_apparent = false:none
|
||||||
|
csharp_style_var_elsewhere = false:suggestion
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||||
|
|
||||||
|
# name all constant fields using PascalCase
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
|
||||||
|
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
|
||||||
|
dotnet_naming_symbols.constant_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.constant_fields.required_modifiers = const
|
||||||
|
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# static fields should have s_ prefix
|
||||||
|
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
|
||||||
|
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
|
||||||
|
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
|
||||||
|
dotnet_naming_symbols.static_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.static_fields.required_modifiers = static
|
||||||
|
dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
|
||||||
|
dotnet_naming_style.static_prefix_style.required_prefix = _
|
||||||
|
dotnet_naming_style.static_prefix_style.capitalization = camel_case
|
||||||
|
|
||||||
|
# internal and private fields should be _camelCase
|
||||||
|
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
|
||||||
|
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
|
||||||
|
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
|
||||||
|
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||||
|
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||||
|
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||||
|
|
||||||
|
# Code style defaults
|
||||||
|
csharp_using_directive_placement = outside_namespace:suggestion
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
csharp_prefer_braces = true:silent
|
||||||
|
csharp_preserve_single_line_blocks = true:none
|
||||||
|
csharp_preserve_single_line_statements = false:none
|
||||||
|
csharp_prefer_static_local_function = true:suggestion
|
||||||
|
csharp_prefer_simple_using_statement = false:none
|
||||||
|
csharp_style_prefer_switch_expression = true:suggestion
|
||||||
|
dotnet_style_readonly_field = true:suggestion
|
||||||
|
|
||||||
|
# Expression-level preferences
|
||||||
|
dotnet_style_object_initializer = true:suggestion
|
||||||
|
dotnet_style_collection_initializer = true:suggestion
|
||||||
|
dotnet_style_explicit_tuple_names = true:suggestion
|
||||||
|
dotnet_style_coalesce_expression = true:suggestion
|
||||||
|
dotnet_style_null_propagation = true:suggestion
|
||||||
|
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
|
||||||
|
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||||
|
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||||
|
dotnet_style_prefer_auto_properties = true:suggestion
|
||||||
|
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||||
|
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||||
|
csharp_prefer_simple_default_expression = true:suggestion
|
||||||
|
|
||||||
|
# Expression-bodied members
|
||||||
|
csharp_style_expression_bodied_methods = true:silent
|
||||||
|
csharp_style_expression_bodied_constructors = true:silent
|
||||||
|
csharp_style_expression_bodied_operators = true:silent
|
||||||
|
csharp_style_expression_bodied_properties = true:silent
|
||||||
|
csharp_style_expression_bodied_indexers = true:silent
|
||||||
|
csharp_style_expression_bodied_accessors = true:silent
|
||||||
|
csharp_style_expression_bodied_lambdas = true:silent
|
||||||
|
csharp_style_expression_bodied_local_functions = true:silent
|
||||||
|
|
||||||
|
# Pattern matching
|
||||||
|
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||||
|
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||||
|
csharp_style_inlined_variable_declaration = true:suggestion
|
||||||
|
|
||||||
|
# Null checking preferences
|
||||||
|
csharp_style_throw_expression = true:suggestion
|
||||||
|
csharp_style_conditional_delegate_call = true:suggestion
|
||||||
|
|
||||||
|
# Other features
|
||||||
|
csharp_style_prefer_index_operator = false:none
|
||||||
|
csharp_style_prefer_range_operator = false:none
|
||||||
|
csharp_style_pattern_local_over_anonymous_function = false:none
|
||||||
|
|
||||||
|
# Space preferences
|
||||||
|
csharp_space_after_cast = false
|
||||||
|
csharp_space_after_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_after_comma = true
|
||||||
|
csharp_space_after_dot = false
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_after_semicolon_in_for_statement = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_around_declaration_statements = do_not_ignore
|
||||||
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_before_comma = false
|
||||||
|
csharp_space_before_dot = false
|
||||||
|
csharp_space_before_open_square_brackets = false
|
||||||
|
csharp_space_before_semicolon_in_for_statement = false
|
||||||
|
csharp_space_between_empty_square_brackets = false
|
||||||
|
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_parentheses = false
|
||||||
|
csharp_space_between_square_brackets = false
|
||||||
|
|
||||||
|
# Analyzers
|
||||||
|
dotnet_code_quality.ca1802.api_surface = private, internal
|
||||||
|
|
||||||
|
# CS1591: Missing XML comment for publicly visible type or member
|
||||||
|
dotnet_diagnostic.CS1591.severity = suggestion
|
||||||
|
|
||||||
|
# Xml project files
|
||||||
|
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{csproj,vbproj,proj,nativeproj,locproj}]
|
||||||
|
charset = utf-8
|
||||||
|
|
||||||
|
# Xml files
|
||||||
|
[*.{xml,stylecop,resx,ruleset}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Xml config files
|
||||||
|
[*.{props,targets,config,nuspec}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# YAML config files
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
12
LibreHardwareMonitor-0.9.4/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [phyxionnl] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||||
20
LibreHardwareMonitor-0.9.4/.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# To get started with Dependabot version updates, you'll need to specify which
|
||||||
|
# package ecosystems to update and where the package manifests are located.
|
||||||
|
# Please see the documentation for all configuration options:
|
||||||
|
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
# LibreHardwareMonitor.csproj
|
||||||
|
- package-ecosystem: "nuget"
|
||||||
|
directory: "/LibreHardwareMonitor"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
|
||||||
|
# LibreHardwareMonitorLib.csproj
|
||||||
|
- package-ecosystem: "nuget"
|
||||||
|
directory: "/LibreHardwareMonitorLib"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
75
LibreHardwareMonitor-0.9.4/.github/workflows/master.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
name: master
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-2022
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: nuget/setup-nuget@v2
|
||||||
|
- uses: microsoft/setup-msbuild@v1.1
|
||||||
|
with:
|
||||||
|
msbuild-architecture: x64
|
||||||
|
|
||||||
|
- uses: dorny/paths-filter@v2
|
||||||
|
id: changes
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
buildprops:
|
||||||
|
- 'Directory.Build.props'
|
||||||
|
|
||||||
|
- name: Update version
|
||||||
|
if: steps.changes.outputs.buildprops == 'false'
|
||||||
|
run: |
|
||||||
|
(Get-Content Directory.Build.props) | % {
|
||||||
|
$m = [regex]::match($_, '<Version>(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?</Version>');
|
||||||
|
if(!$m.Success -or $m.Groups[4].Success -or $m.Groups[5].Success) { $_; }
|
||||||
|
else { $_ -replace $m.Value, ("<Version>{0}.{1}.{2}-pre${{ github.run_number }}</Version>" -f $m.Groups[1].Value,$m.Groups[2].Value,([convert]::ToInt32($m.Groups[3].Value)+1)); }
|
||||||
|
} | Set-Content Directory.Build.props
|
||||||
|
|
||||||
|
- name: NuGet restore
|
||||||
|
run: nuget restore LibreHardwareMonitor.sln
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: msbuild LibreHardwareMonitor.sln -p:Configuration=Release -m
|
||||||
|
|
||||||
|
- name: Publish net472
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitor-net472
|
||||||
|
path: |
|
||||||
|
bin/Release/net472
|
||||||
|
|
||||||
|
- name: Publish netstandard20
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-netstandard20
|
||||||
|
path: |
|
||||||
|
bin/Release/netstandard2.0
|
||||||
|
|
||||||
|
- name: Publish net60
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-net60
|
||||||
|
path: |
|
||||||
|
bin/Release/net6.0
|
||||||
|
|
||||||
|
- name: Publish net70
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-net70
|
||||||
|
path: |
|
||||||
|
bin/Release/net7.0
|
||||||
|
|
||||||
|
- name: Publish nupkg
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-nupkg
|
||||||
|
path: |
|
||||||
|
bin/Release/LibreHardwareMonitorLib.*.nupkg
|
||||||
|
|
||||||
|
- name: Publish to NuGet
|
||||||
|
run: nuget push **\*.nupkg -Source 'https://api.nuget.org/v3/index.json' -ApiKey ${{secrets.NUGET_API_KEY}}
|
||||||
71
LibreHardwareMonitor-0.9.4/.github/workflows/pull requests.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
name: pull requests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [master]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: windows-2022
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: nuget/setup-nuget@v2
|
||||||
|
- uses: microsoft/setup-msbuild@v1.1
|
||||||
|
with:
|
||||||
|
msbuild-architecture: x64
|
||||||
|
|
||||||
|
- uses: dorny/paths-filter@v2
|
||||||
|
id: changes
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
buildprops:
|
||||||
|
- 'Directory.Build.props'
|
||||||
|
- name: Update version
|
||||||
|
if: steps.changes.outputs.buildprops == 'false'
|
||||||
|
run: |
|
||||||
|
(Get-Content Directory.Build.props) | % {
|
||||||
|
$m = [regex]::match($_, '<Version>(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?</Version>');
|
||||||
|
if(!$m.Success -or $m.Groups[4].Success -or $m.Groups[5].Success) { $_; }
|
||||||
|
else { $_ -replace $m.Value, ("<Version>{0}.{1}.{2}-ci${{ github.run_number }}</Version>" -f $m.Groups[1].Value,$m.Groups[2].Value,([convert]::ToInt32($m.Groups[3].Value)+1)); }
|
||||||
|
} | Set-Content Directory.Build.props
|
||||||
|
|
||||||
|
- name: NuGet restore
|
||||||
|
run: nuget restore LibreHardwareMonitor.sln
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: msbuild LibreHardwareMonitor.sln -p:Configuration=Release -m
|
||||||
|
|
||||||
|
- name: Publish net472
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitor-net472
|
||||||
|
path: |
|
||||||
|
bin/Release/net472
|
||||||
|
|
||||||
|
- name: Publish netstandard20
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-netstandard20
|
||||||
|
path: |
|
||||||
|
bin/Release/netstandard2.0
|
||||||
|
|
||||||
|
- name: Publish net60
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-net60
|
||||||
|
path: |
|
||||||
|
bin/Release/net6.0
|
||||||
|
|
||||||
|
- name: Publish net70
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-net70
|
||||||
|
path: |
|
||||||
|
bin/Release/net7.0
|
||||||
|
|
||||||
|
- name: Publish nupkg
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: LibreHardwareMonitorLib-nupkg
|
||||||
|
path: |
|
||||||
|
bin/Release/LibreHardwareMonitorLib.*.nupkg
|
||||||
7
LibreHardwareMonitor-0.9.4/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
*.user
|
||||||
|
*.suo
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
.idea/
|
||||||
|
.vs/
|
||||||
|
packages/
|
||||||
121
LibreHardwareMonitor-0.9.4/Aga.Controls/Aga.Controls.csproj
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
|
<TargetFramework>net472</TargetFramework>
|
||||||
|
<AssemblyTitle>Aga.Controls</AssemblyTitle>
|
||||||
|
<Description>http://sourceforge.net/projects/treeviewadv/</Description>
|
||||||
|
<Copyright>Copyright © Andrey Gliznetsov 2006 - 2009</Copyright>
|
||||||
|
<AssemblyVersion>1.7.0.0</AssemblyVersion>
|
||||||
|
<FileVersion>1.7.0.0</FileVersion>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<OutputPath>..\bin\$(Configuration)\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<DefineConstants>TRACE;DEBUG;PERF_TEST</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System.Design" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeIntegerTextBox.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeDecimalTextBox.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="NumericTextBox.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\ExpandingIcon.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\InteractiveControl.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\TreeViewAdv.Draw.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\TreeViewAdv.Editor.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\TreeViewAdv.Input.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeNumericUpDown.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\TreeViewAdv.Properties.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\BaseTextControl.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\EditableControl.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeComboBox.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\TreeColumn.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeControl.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\BindableControl.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeCheckBox.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeIcon.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodePlusMinus.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeTextBox.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\NodeControls\NodeStateIcon.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\TreeViewAdv.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Update="Tree\TreeViewAdv.Designer.cs">
|
||||||
|
<DependentUpon>TreeViewAdv.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Resources\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Update="Properties\Resources.resx">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Update="Tree\TreeViewAdv.resx">
|
||||||
|
<DependentUpon>TreeViewAdv.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Tree\ClassDiagram.cd" />
|
||||||
|
<None Include="Tree\NodeControls\ClassDiagram.cd" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Tree\ColumnCollection.cs" />
|
||||||
|
<Compile Remove="Tree\NativeMethods.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
20
LibreHardwareMonitor-0.9.4/Aga.Controls/Aga.Controls.sln
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Visual Studio 2010
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aga.Controls", "Aga.Controls.csproj", "{E73BB233-D88B-44A7-A98F-D71EE158381D}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{E73BB233-D88B-44A7-A98F-D71EE158381D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{E73BB233-D88B-44A7-A98F-D71EE158381D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
46
LibreHardwareMonitor-0.9.4/Aga.Controls/BitmapHelper.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
public static class BitmapHelper
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct PixelData
|
||||||
|
{
|
||||||
|
public byte B;
|
||||||
|
public byte G;
|
||||||
|
public byte R;
|
||||||
|
public byte A;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetAlphaChanelValue(Bitmap image, byte value)
|
||||||
|
{
|
||||||
|
if (image == null)
|
||||||
|
throw new ArgumentNullException("image");
|
||||||
|
if (image.PixelFormat != PixelFormat.Format32bppArgb)
|
||||||
|
throw new ArgumentException("Wrong PixelFormat");
|
||||||
|
|
||||||
|
BitmapData bitmapData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
|
||||||
|
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
PixelData* pPixel = (PixelData*)bitmapData.Scan0;
|
||||||
|
for (int i = 0; i < bitmapData.Height; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < bitmapData.Width; j++)
|
||||||
|
{
|
||||||
|
pPixel->A = value;
|
||||||
|
pPixel++;
|
||||||
|
}
|
||||||
|
pPixel += bitmapData.Stride - (bitmapData.Width * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image.UnlockBits(bitmapData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
864
LibreHardwareMonitor-0.9.4/Aga.Controls/GifDecoder.cs
Normal file
@@ -0,0 +1,864 @@
|
|||||||
|
#pragma warning disable 675 // Bitwise-or operator used on a sign-extended operand
|
||||||
|
|
||||||
|
#region Java Info
|
||||||
|
/**
|
||||||
|
* Class GifDecoder - Decodes a GIF file into one or more frames.
|
||||||
|
* <br><pre>
|
||||||
|
* Example:
|
||||||
|
* GifDecoder d = new GifDecoder();
|
||||||
|
* d.read("sample.gif");
|
||||||
|
* int n = d.getFrameCount();
|
||||||
|
* for (int i = 0; i < n; i++) {
|
||||||
|
* BufferedImage frame = d.getFrame(i); // frame i
|
||||||
|
* int t = d.getDelay(i); // display duration of frame in milliseconds
|
||||||
|
* // do something with frame
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* No copyright asserted on the source code of this class. May be used for
|
||||||
|
* any purpose, however, refer to the Unisys LZW patent for any additional
|
||||||
|
* restrictions. Please forward any corrections to kweiner@fmsware.com.
|
||||||
|
*
|
||||||
|
* @author Kevin Weiner, FM Software; LZW decoder adapted from John Cristy's ImageMagick.
|
||||||
|
* @version 1.03 November 2003
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
public class GifFrame
|
||||||
|
{
|
||||||
|
private Image _image;
|
||||||
|
public Image Image
|
||||||
|
{
|
||||||
|
get { return _image; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _delay;
|
||||||
|
public int Delay
|
||||||
|
{
|
||||||
|
get { return _delay; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public GifFrame(Image im, int del)
|
||||||
|
{
|
||||||
|
_image = im;
|
||||||
|
_delay = del;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GifDecoder
|
||||||
|
{
|
||||||
|
public const int StatusOK = 0;//File read status: No errors.
|
||||||
|
public const int StatusFormatError = 1; //File read status: Error decoding file (may be partially decoded)
|
||||||
|
public const int StatusOpenError = 2; //Unable to open source.
|
||||||
|
|
||||||
|
private Stream inStream;
|
||||||
|
private int status;
|
||||||
|
|
||||||
|
private int width; // full image width
|
||||||
|
private int height; // full image height
|
||||||
|
private bool gctFlag; // global color table used
|
||||||
|
private int gctSize; // size of global color table
|
||||||
|
private int loopCount = 1; // iterations; 0 = repeat forever
|
||||||
|
|
||||||
|
private int[] gct; // global color table
|
||||||
|
private int[] lct; // local color table
|
||||||
|
private int[] act; // active color table
|
||||||
|
|
||||||
|
private int bgIndex; // background color index
|
||||||
|
private int bgColor; // background color
|
||||||
|
private int lastBgColor; // previous bg color
|
||||||
|
private int pixelAspect; // pixel aspect ratio
|
||||||
|
|
||||||
|
private bool lctFlag; // local color table flag
|
||||||
|
private bool interlace; // interlace flag
|
||||||
|
private int lctSize; // local color table size
|
||||||
|
|
||||||
|
private int ix, iy, iw, ih; // current image rectangle
|
||||||
|
private Rectangle lastRect; // last image rect
|
||||||
|
private Image image; // current frame
|
||||||
|
private Bitmap bitmap;
|
||||||
|
private Image lastImage; // previous frame
|
||||||
|
|
||||||
|
private byte[] block = new byte[256]; // current data block
|
||||||
|
private int blockSize = 0; // block size
|
||||||
|
|
||||||
|
// last graphic control extension info
|
||||||
|
private int dispose = 0;
|
||||||
|
// 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
|
||||||
|
private int lastDispose = 0;
|
||||||
|
private bool transparency = false; // use transparent color
|
||||||
|
private int delay = 0; // delay in milliseconds
|
||||||
|
private int transIndex; // transparent color index
|
||||||
|
|
||||||
|
private const int MaxStackSize = 4096;
|
||||||
|
// max decoder pixel stack size
|
||||||
|
|
||||||
|
// LZW decoder working arrays
|
||||||
|
private short[] prefix;
|
||||||
|
private byte[] suffix;
|
||||||
|
private byte[] pixelStack;
|
||||||
|
private byte[] pixels;
|
||||||
|
|
||||||
|
private ArrayList frames; // frames read from current file
|
||||||
|
private int frameCount;
|
||||||
|
private bool _makeTransparent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of frames read from file.
|
||||||
|
* @return frame count
|
||||||
|
*/
|
||||||
|
public int FrameCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return frameCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the first (or only) image read.
|
||||||
|
*
|
||||||
|
* @return BufferedImage containing first frame, or null if none.
|
||||||
|
*/
|
||||||
|
public Image Image
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetFrame(0).Image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the "Netscape" iteration count, if any.
|
||||||
|
* A count of 0 means repeat indefinitiely.
|
||||||
|
*
|
||||||
|
* @return iteration count if one was specified, else 1.
|
||||||
|
*/
|
||||||
|
public int LoopCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return loopCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GifDecoder(Stream stream, bool makeTransparent)
|
||||||
|
{
|
||||||
|
_makeTransparent = makeTransparent;
|
||||||
|
if (Read(stream) != 0)
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates new frame image from current data (and previous
|
||||||
|
* frames as specified by their disposition codes).
|
||||||
|
*/
|
||||||
|
private int[] GetPixels(Bitmap bitmap)
|
||||||
|
{
|
||||||
|
int [] pixels = new int [ 3 * image.Width * image.Height ];
|
||||||
|
int count = 0;
|
||||||
|
for (int th = 0; th < image.Height; th++)
|
||||||
|
{
|
||||||
|
for (int tw = 0; tw < image.Width; tw++)
|
||||||
|
{
|
||||||
|
Color color = bitmap.GetPixel(tw, th);
|
||||||
|
pixels[count] = color.R;
|
||||||
|
count++;
|
||||||
|
pixels[count] = color.G;
|
||||||
|
count++;
|
||||||
|
pixels[count] = color.B;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPixels(int[] pixels)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (int th = 0; th < image.Height; th++)
|
||||||
|
{
|
||||||
|
for (int tw = 0; tw < image.Width; tw++)
|
||||||
|
{
|
||||||
|
Color color = Color.FromArgb( pixels[count++] );
|
||||||
|
bitmap.SetPixel( tw, th, color );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_makeTransparent)
|
||||||
|
bitmap.MakeTransparent(bitmap.GetPixel(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetPixels()
|
||||||
|
{
|
||||||
|
// expose destination image's pixels as int array
|
||||||
|
// int[] dest =
|
||||||
|
// (( int ) image.getRaster().getDataBuffer()).getData();
|
||||||
|
int[] dest = GetPixels( bitmap );
|
||||||
|
|
||||||
|
// fill in starting image contents based on last image's dispose code
|
||||||
|
if (lastDispose > 0)
|
||||||
|
{
|
||||||
|
if (lastDispose == 3)
|
||||||
|
{
|
||||||
|
// use image before last
|
||||||
|
int n = frameCount - 2;
|
||||||
|
if (n > 0)
|
||||||
|
{
|
||||||
|
lastImage = GetFrame(n - 1).Image;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastImage = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastImage != null)
|
||||||
|
{
|
||||||
|
// int[] prev =
|
||||||
|
// ((DataBufferInt) lastImage.getRaster().getDataBuffer()).getData();
|
||||||
|
int[] prev = GetPixels( new Bitmap( lastImage ) );
|
||||||
|
Array.Copy(prev, 0, dest, 0, width * height);
|
||||||
|
// copy pixels
|
||||||
|
|
||||||
|
if (lastDispose == 2)
|
||||||
|
{
|
||||||
|
// fill last image rect area with background color
|
||||||
|
Graphics g = Graphics.FromImage( image );
|
||||||
|
Color c = Color.Empty;
|
||||||
|
if (transparency)
|
||||||
|
{
|
||||||
|
c = Color.FromArgb( 0, 0, 0, 0 ); // assume background is transparent
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c = Color.FromArgb( lastBgColor ) ;
|
||||||
|
// c = new Color(lastBgColor); // use given background color
|
||||||
|
}
|
||||||
|
Brush brush = new SolidBrush( c );
|
||||||
|
g.FillRectangle( brush, lastRect );
|
||||||
|
brush.Dispose();
|
||||||
|
g.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy each source line to the appropriate place in the destination
|
||||||
|
int pass = 1;
|
||||||
|
int inc = 8;
|
||||||
|
int iline = 0;
|
||||||
|
for (int i = 0; i < ih; i++)
|
||||||
|
{
|
||||||
|
int line = i;
|
||||||
|
if (interlace)
|
||||||
|
{
|
||||||
|
if (iline >= ih)
|
||||||
|
{
|
||||||
|
pass++;
|
||||||
|
switch (pass)
|
||||||
|
{
|
||||||
|
case 2 :
|
||||||
|
iline = 4;
|
||||||
|
break;
|
||||||
|
case 3 :
|
||||||
|
iline = 2;
|
||||||
|
inc = 4;
|
||||||
|
break;
|
||||||
|
case 4 :
|
||||||
|
iline = 1;
|
||||||
|
inc = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
line = iline;
|
||||||
|
iline += inc;
|
||||||
|
}
|
||||||
|
line += iy;
|
||||||
|
if (line < height)
|
||||||
|
{
|
||||||
|
int k = line * width;
|
||||||
|
int dx = k + ix; // start of line in dest
|
||||||
|
int dlim = dx + iw; // end of dest line
|
||||||
|
if ((k + width) < dlim)
|
||||||
|
{
|
||||||
|
dlim = k + width; // past dest edge
|
||||||
|
}
|
||||||
|
int sx = i * iw; // start of line in source
|
||||||
|
while (dx < dlim)
|
||||||
|
{
|
||||||
|
// map color and insert in destination
|
||||||
|
int index = ((int) pixels[sx++]) & 0xff;
|
||||||
|
int c = act[index];
|
||||||
|
if (c != 0)
|
||||||
|
{
|
||||||
|
dest[dx] = c;
|
||||||
|
}
|
||||||
|
dx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SetPixels( dest );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the image contents of frame n.
|
||||||
|
*
|
||||||
|
* @return BufferedImage representation of frame.
|
||||||
|
*/
|
||||||
|
public GifFrame GetFrame(int n)
|
||||||
|
{
|
||||||
|
if ((n >= 0) && (n < frameCount))
|
||||||
|
return (GifFrame)frames[n];
|
||||||
|
else
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets image size.
|
||||||
|
*
|
||||||
|
* @return GIF image dimensions
|
||||||
|
*/
|
||||||
|
public Size FrameSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads GIF image from stream
|
||||||
|
*
|
||||||
|
* @param BufferedInputStream containing GIF file.
|
||||||
|
* @return read status code (0 = no errors)
|
||||||
|
*/
|
||||||
|
private int Read( Stream inStream )
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
if ( inStream != null)
|
||||||
|
{
|
||||||
|
this.inStream = inStream;
|
||||||
|
ReadHeader();
|
||||||
|
if (!Error())
|
||||||
|
{
|
||||||
|
ReadContents();
|
||||||
|
if (frameCount < 0)
|
||||||
|
{
|
||||||
|
status = StatusFormatError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inStream.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status = StatusOpenError;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes LZW image data into pixel array.
|
||||||
|
* Adapted from John Cristy's ImageMagick.
|
||||||
|
*/
|
||||||
|
private void DecodeImageData()
|
||||||
|
{
|
||||||
|
int NullCode = -1;
|
||||||
|
int npix = iw * ih;
|
||||||
|
int available,
|
||||||
|
clear,
|
||||||
|
code_mask,
|
||||||
|
code_size,
|
||||||
|
end_of_information,
|
||||||
|
in_code,
|
||||||
|
old_code,
|
||||||
|
bits,
|
||||||
|
code,
|
||||||
|
count,
|
||||||
|
i,
|
||||||
|
datum,
|
||||||
|
data_size,
|
||||||
|
first,
|
||||||
|
top,
|
||||||
|
bi,
|
||||||
|
pi;
|
||||||
|
|
||||||
|
if ((pixels == null) || (pixels.Length < npix))
|
||||||
|
{
|
||||||
|
pixels = new byte[npix]; // allocate new pixel array
|
||||||
|
}
|
||||||
|
if (prefix == null) prefix = new short[MaxStackSize];
|
||||||
|
if (suffix == null) suffix = new byte[MaxStackSize];
|
||||||
|
if (pixelStack == null) pixelStack = new byte[MaxStackSize + 1];
|
||||||
|
|
||||||
|
// Initialize GIF data stream decoder.
|
||||||
|
|
||||||
|
data_size = Read();
|
||||||
|
clear = 1 << data_size;
|
||||||
|
end_of_information = clear + 1;
|
||||||
|
available = clear + 2;
|
||||||
|
old_code = NullCode;
|
||||||
|
code_size = data_size + 1;
|
||||||
|
code_mask = (1 << code_size) - 1;
|
||||||
|
for (code = 0; code < clear; code++)
|
||||||
|
{
|
||||||
|
prefix[code] = 0;
|
||||||
|
suffix[code] = (byte) code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode GIF pixel stream.
|
||||||
|
|
||||||
|
datum = bits = count = first = top = pi = bi = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < npix;)
|
||||||
|
{
|
||||||
|
if (top == 0)
|
||||||
|
{
|
||||||
|
if (bits < code_size)
|
||||||
|
{
|
||||||
|
// Load bytes until there are enough bits for a code.
|
||||||
|
if (count == 0)
|
||||||
|
{
|
||||||
|
// Read a new data block.
|
||||||
|
count = ReadBlock();
|
||||||
|
if (count <= 0)
|
||||||
|
break;
|
||||||
|
bi = 0;
|
||||||
|
}
|
||||||
|
datum += (((int) block[bi]) & 0xff) << bits;
|
||||||
|
bits += 8;
|
||||||
|
bi++;
|
||||||
|
count--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next code.
|
||||||
|
|
||||||
|
code = datum & code_mask;
|
||||||
|
datum >>= code_size;
|
||||||
|
bits -= code_size;
|
||||||
|
|
||||||
|
// Interpret the code
|
||||||
|
|
||||||
|
if ((code > available) || (code == end_of_information))
|
||||||
|
break;
|
||||||
|
if (code == clear)
|
||||||
|
{
|
||||||
|
// Reset decoder.
|
||||||
|
code_size = data_size + 1;
|
||||||
|
code_mask = (1 << code_size) - 1;
|
||||||
|
available = clear + 2;
|
||||||
|
old_code = NullCode;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (old_code == NullCode)
|
||||||
|
{
|
||||||
|
pixelStack[top++] = suffix[code];
|
||||||
|
old_code = code;
|
||||||
|
first = code;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
in_code = code;
|
||||||
|
if (code == available)
|
||||||
|
{
|
||||||
|
pixelStack[top++] = (byte) first;
|
||||||
|
code = old_code;
|
||||||
|
}
|
||||||
|
while (code > clear)
|
||||||
|
{
|
||||||
|
pixelStack[top++] = suffix[code];
|
||||||
|
code = prefix[code];
|
||||||
|
}
|
||||||
|
first = ((int) suffix[code]) & 0xff;
|
||||||
|
|
||||||
|
// Add a new string to the string table,
|
||||||
|
|
||||||
|
if (available >= MaxStackSize)
|
||||||
|
break;
|
||||||
|
pixelStack[top++] = (byte) first;
|
||||||
|
prefix[available] = (short) old_code;
|
||||||
|
suffix[available] = (byte) first;
|
||||||
|
available++;
|
||||||
|
if (((available & code_mask) == 0)
|
||||||
|
&& (available < MaxStackSize))
|
||||||
|
{
|
||||||
|
code_size++;
|
||||||
|
code_mask += available;
|
||||||
|
}
|
||||||
|
old_code = in_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop a pixel off the pixel stack.
|
||||||
|
|
||||||
|
top--;
|
||||||
|
pixels[pi++] = pixelStack[top];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = pi; i < npix; i++)
|
||||||
|
{
|
||||||
|
pixels[i] = 0; // clear missing pixels
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if an error was encountered during reading/decoding
|
||||||
|
*/
|
||||||
|
private bool Error()
|
||||||
|
{
|
||||||
|
return status != StatusOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes or re-initializes reader
|
||||||
|
*/
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
status = StatusOK;
|
||||||
|
frameCount = 0;
|
||||||
|
frames = new ArrayList();
|
||||||
|
gct = null;
|
||||||
|
lct = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a single byte from the input stream.
|
||||||
|
*/
|
||||||
|
private int Read()
|
||||||
|
{
|
||||||
|
int curByte = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
curByte = inStream.ReadByte();
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
status = StatusFormatError;
|
||||||
|
}
|
||||||
|
return curByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads next variable length block from input.
|
||||||
|
*
|
||||||
|
* @return number of bytes stored in "buffer"
|
||||||
|
*/
|
||||||
|
private int ReadBlock()
|
||||||
|
{
|
||||||
|
blockSize = Read();
|
||||||
|
int n = 0;
|
||||||
|
if (blockSize > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
while (n < blockSize)
|
||||||
|
{
|
||||||
|
count = inStream.Read(block, n, blockSize - n);
|
||||||
|
if (count == -1)
|
||||||
|
break;
|
||||||
|
n += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n < blockSize)
|
||||||
|
{
|
||||||
|
status = StatusFormatError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads color table as 256 RGB integer values
|
||||||
|
*
|
||||||
|
* @param ncolors int number of colors to read
|
||||||
|
* @return int array containing 256 colors (packed ARGB with full alpha)
|
||||||
|
*/
|
||||||
|
private int[] ReadColorTable(int ncolors)
|
||||||
|
{
|
||||||
|
int nbytes = 3 * ncolors;
|
||||||
|
int[] tab = null;
|
||||||
|
byte[] c = new byte[nbytes];
|
||||||
|
int n = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
n = inStream.Read(c, 0, c.Length );
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
if (n < nbytes)
|
||||||
|
{
|
||||||
|
status = StatusFormatError;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tab = new int[256]; // max size to avoid bounds checks
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
while (i < ncolors)
|
||||||
|
{
|
||||||
|
int r = ((int) c[j++]) & 0xff;
|
||||||
|
int g = ((int) c[j++]) & 0xff;
|
||||||
|
int b = ((int) c[j++]) & 0xff;
|
||||||
|
tab[i++] = ( int ) ( 0xff000000 | (r << 16) | (g << 8) | b );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main file parser. Reads GIF content blocks.
|
||||||
|
*/
|
||||||
|
private void ReadContents()
|
||||||
|
{
|
||||||
|
// read GIF file content blocks
|
||||||
|
bool done = false;
|
||||||
|
while (!(done || Error()))
|
||||||
|
{
|
||||||
|
int code = Read();
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
|
||||||
|
case 0x2C : // image separator
|
||||||
|
ReadImage();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x21 : // extension
|
||||||
|
code = Read();
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case 0xf9 : // graphics control extension
|
||||||
|
ReadGraphicControlExt();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xff : // application extension
|
||||||
|
ReadBlock();
|
||||||
|
String app = "";
|
||||||
|
for (int i = 0; i < 11; i++)
|
||||||
|
{
|
||||||
|
app += (char) block[i];
|
||||||
|
}
|
||||||
|
if (app.Equals("NETSCAPE2.0"))
|
||||||
|
{
|
||||||
|
ReadNetscapeExt();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Skip(); // don't care
|
||||||
|
break;
|
||||||
|
|
||||||
|
default : // uninteresting extension
|
||||||
|
Skip();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x3b : // terminator
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x00 : // bad byte, but keep going and see what happens
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
status = StatusFormatError;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads Graphics Control Extension values
|
||||||
|
*/
|
||||||
|
private void ReadGraphicControlExt()
|
||||||
|
{
|
||||||
|
Read(); // block size
|
||||||
|
int packed = Read(); // packed fields
|
||||||
|
dispose = (packed & 0x1c) >> 2; // disposal method
|
||||||
|
if (dispose == 0)
|
||||||
|
{
|
||||||
|
dispose = 1; // elect to keep old image if discretionary
|
||||||
|
}
|
||||||
|
transparency = (packed & 1) != 0;
|
||||||
|
delay = ReadShort() * 10; // delay in milliseconds
|
||||||
|
transIndex = Read(); // transparent color index
|
||||||
|
Read(); // block terminator
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads GIF file header information.
|
||||||
|
*/
|
||||||
|
private void ReadHeader()
|
||||||
|
{
|
||||||
|
String id = "";
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
id += (char) Read();
|
||||||
|
}
|
||||||
|
if (!id.StartsWith("GIF"))
|
||||||
|
{
|
||||||
|
status = StatusFormatError;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadLSD();
|
||||||
|
if (gctFlag && !Error())
|
||||||
|
{
|
||||||
|
gct = ReadColorTable(gctSize);
|
||||||
|
bgColor = gct[bgIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads next frame image
|
||||||
|
*/
|
||||||
|
private void ReadImage()
|
||||||
|
{
|
||||||
|
ix = ReadShort(); // (sub)image position & size
|
||||||
|
iy = ReadShort();
|
||||||
|
iw = ReadShort();
|
||||||
|
ih = ReadShort();
|
||||||
|
|
||||||
|
int packed = Read();
|
||||||
|
lctFlag = (packed & 0x80) != 0; // 1 - local color table flag
|
||||||
|
interlace = (packed & 0x40) != 0; // 2 - interlace flag
|
||||||
|
// 3 - sort flag
|
||||||
|
// 4-5 - reserved
|
||||||
|
lctSize = 2 << (packed & 7); // 6-8 - local color table size
|
||||||
|
|
||||||
|
if (lctFlag)
|
||||||
|
{
|
||||||
|
lct = ReadColorTable(lctSize); // read table
|
||||||
|
act = lct; // make local table active
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
act = gct; // make global table active
|
||||||
|
if (bgIndex == transIndex)
|
||||||
|
bgColor = 0;
|
||||||
|
}
|
||||||
|
int save = 0;
|
||||||
|
if (transparency)
|
||||||
|
{
|
||||||
|
save = act[transIndex];
|
||||||
|
act[transIndex] = 0; // set transparent color if specified
|
||||||
|
}
|
||||||
|
|
||||||
|
if (act == null)
|
||||||
|
{
|
||||||
|
status = StatusFormatError; // no color table defined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Error()) return;
|
||||||
|
|
||||||
|
DecodeImageData(); // decode pixel data
|
||||||
|
Skip();
|
||||||
|
|
||||||
|
if (Error()) return;
|
||||||
|
|
||||||
|
frameCount++;
|
||||||
|
|
||||||
|
// create new image to receive frame data
|
||||||
|
// image =
|
||||||
|
// new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
|
||||||
|
|
||||||
|
bitmap = new Bitmap( width, height );
|
||||||
|
image = bitmap;
|
||||||
|
SetPixels(); // transfer pixel data to image
|
||||||
|
|
||||||
|
frames.Add(new GifFrame(bitmap, delay)); // add image to frame list
|
||||||
|
|
||||||
|
if (transparency)
|
||||||
|
{
|
||||||
|
act[transIndex] = save;
|
||||||
|
}
|
||||||
|
ResetFrame();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads Logical Screen Descriptor
|
||||||
|
*/
|
||||||
|
private void ReadLSD()
|
||||||
|
{
|
||||||
|
|
||||||
|
// logical screen size
|
||||||
|
width = ReadShort();
|
||||||
|
height = ReadShort();
|
||||||
|
|
||||||
|
// packed fields
|
||||||
|
int packed = Read();
|
||||||
|
gctFlag = (packed & 0x80) != 0; // 1 : global color table flag
|
||||||
|
// 2-4 : color resolution
|
||||||
|
// 5 : gct sort flag
|
||||||
|
gctSize = 2 << (packed & 7); // 6-8 : gct size
|
||||||
|
|
||||||
|
bgIndex = Read(); // background color index
|
||||||
|
pixelAspect = Read(); // pixel aspect ratio
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads Netscape extenstion to obtain iteration count
|
||||||
|
*/
|
||||||
|
private void ReadNetscapeExt()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ReadBlock();
|
||||||
|
if (block[0] == 1)
|
||||||
|
{
|
||||||
|
// loop count sub-block
|
||||||
|
int b1 = ((int) block[1]) & 0xff;
|
||||||
|
int b2 = ((int) block[2]) & 0xff;
|
||||||
|
loopCount = (b2 << 8) | b1;
|
||||||
|
}
|
||||||
|
} while ((blockSize > 0) && !Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads next 16-bit value, LSB first
|
||||||
|
*/
|
||||||
|
private int ReadShort()
|
||||||
|
{
|
||||||
|
// read 16-bit value, LSB first
|
||||||
|
return Read() | (Read() << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets frame state for reading next image.
|
||||||
|
*/
|
||||||
|
private void ResetFrame()
|
||||||
|
{
|
||||||
|
lastDispose = dispose;
|
||||||
|
lastRect = new Rectangle(ix, iy, iw, ih);
|
||||||
|
lastImage = image;
|
||||||
|
lastBgColor = bgColor;
|
||||||
|
// int dispose = 0;
|
||||||
|
lct = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips variable length blocks up to and including
|
||||||
|
* next zero length block.
|
||||||
|
*/
|
||||||
|
private void Skip()
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ReadBlock();
|
||||||
|
} while ((blockSize > 0) && !Error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
189
LibreHardwareMonitor-0.9.4/Aga.Controls/NumericTextBox.cs
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Restricts the entry of characters to digits, the negative sign,
|
||||||
|
/// the decimal point, and editing keystrokes (backspace).
|
||||||
|
/// It does not handle the AltGr key so any keys that can be created in any
|
||||||
|
/// combination with AltGr these are not filtered
|
||||||
|
/// </summary>
|
||||||
|
public class NumericTextBox : TextBox
|
||||||
|
{
|
||||||
|
private const int WM_PASTE = 0x302;
|
||||||
|
private NumberStyles numberStyle = NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restricts the entry of characters to digits, the negative sign,
|
||||||
|
/// the decimal point, and editing keystrokes (backspace).
|
||||||
|
/// It does not handle the AltGr key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
protected override void OnKeyPress(KeyPressEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnKeyPress(e);
|
||||||
|
|
||||||
|
e.Handled = invalidNumeric(e.KeyChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Main method for verifying allowed keypresses.
|
||||||
|
/// This does not catch cut paste copy ... operations.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool invalidNumeric(char key)
|
||||||
|
{
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
|
||||||
|
string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
|
||||||
|
string negativeSign = numberFormatInfo.NegativeSign;
|
||||||
|
|
||||||
|
string keyString = key.ToString();
|
||||||
|
|
||||||
|
if (Char.IsDigit(key))
|
||||||
|
{
|
||||||
|
// Digits are OK
|
||||||
|
}
|
||||||
|
else if (AllowDecimalSeparator && keyString.Equals(decimalSeparator))
|
||||||
|
{
|
||||||
|
if (Text.IndexOf(decimalSeparator) >= 0)
|
||||||
|
{
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (AllowNegativeSign && keyString.Equals(negativeSign))
|
||||||
|
{
|
||||||
|
if (Text.IndexOf(negativeSign) >= 0)
|
||||||
|
{
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key == '\b')
|
||||||
|
{
|
||||||
|
// Backspace key is OK
|
||||||
|
}
|
||||||
|
else if ((ModifierKeys & (Keys.Control)) != 0)
|
||||||
|
{
|
||||||
|
// Let the edit control handle control and alt key combinations
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Swallow this invalid key and beep
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Method invoked when Windows sends a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="m">Message from Windows.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is over-ridden so that the user can not use
|
||||||
|
/// cut or paste operations to bypass the TextChanging event.
|
||||||
|
/// This catches ContextMenu Paste, Shift+Insert, Ctrl+V,
|
||||||
|
/// While it is generally frowned upon to override WndProc, no
|
||||||
|
/// other simple mechanism was apparent to simultaneously and
|
||||||
|
/// transparently intercept so many different operations.
|
||||||
|
/// </remarks>
|
||||||
|
protected override void WndProc(ref Message m)
|
||||||
|
{
|
||||||
|
// Switch to handle message...
|
||||||
|
switch (m.Msg)
|
||||||
|
{
|
||||||
|
case WM_PASTE:
|
||||||
|
{
|
||||||
|
// Get clipboard object to paste
|
||||||
|
IDataObject clipboardData = Clipboard.GetDataObject();
|
||||||
|
|
||||||
|
// Get text from clipboard data
|
||||||
|
string pasteText = (string)clipboardData.GetData(
|
||||||
|
DataFormats.UnicodeText);
|
||||||
|
|
||||||
|
// Get the number of characters to replace
|
||||||
|
int selectionLength = SelectionLength;
|
||||||
|
|
||||||
|
// If no replacement or insertion, we are done
|
||||||
|
if (pasteText.Length == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (selectionLength != 0)
|
||||||
|
{
|
||||||
|
base.Text = base.Text.Remove(SelectionStart, selectionLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool containsInvalidChars = false;
|
||||||
|
foreach (char c in pasteText)
|
||||||
|
{
|
||||||
|
if (containsInvalidChars)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (invalidNumeric(c))
|
||||||
|
{
|
||||||
|
containsInvalidChars = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!containsInvalidChars)
|
||||||
|
{
|
||||||
|
base.Text = base.Text.Insert(SelectionStart, pasteText);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
base.WndProc(ref m);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int IntValue
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int intValue;
|
||||||
|
Int32.TryParse(this.Text, numberStyle, CultureInfo.CurrentCulture.NumberFormat, out intValue);
|
||||||
|
return intValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public decimal DecimalValue
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
decimal decimalValue;
|
||||||
|
Decimal.TryParse(this.Text, numberStyle, CultureInfo.CurrentCulture.NumberFormat, out decimalValue);
|
||||||
|
return decimalValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool allowNegativeSign;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool AllowNegativeSign
|
||||||
|
{
|
||||||
|
get { return allowNegativeSign; }
|
||||||
|
set { allowNegativeSign = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool allowDecimalSeparator;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool AllowDecimalSeparator
|
||||||
|
{
|
||||||
|
get { return allowDecimalSeparator; }
|
||||||
|
set { allowDecimalSeparator = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
136
LibreHardwareMonitor-0.9.4/Aga.Controls/PerformanceAnalyzer.cs
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Is used to analyze code performance
|
||||||
|
/// </summary>
|
||||||
|
public static class PerformanceAnalyzer
|
||||||
|
{
|
||||||
|
public class PerformanceInfo
|
||||||
|
{
|
||||||
|
private string _name;
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return _name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _count = 0;
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _count; }
|
||||||
|
set { _count = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private double _totalTime = 0;
|
||||||
|
public double TotalTime
|
||||||
|
{
|
||||||
|
get { return _totalTime; }
|
||||||
|
set { _totalTime = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Int64 _start;
|
||||||
|
public Int64 Start
|
||||||
|
{
|
||||||
|
get { return _start; }
|
||||||
|
set { _start = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public PerformanceInfo(string name)
|
||||||
|
{
|
||||||
|
_name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, PerformanceInfo> _performances = new Dictionary<string, PerformanceInfo>();
|
||||||
|
|
||||||
|
public static IEnumerable<PerformanceInfo> Performances
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _performances.Values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
public static void Start(string pieceOfCode)
|
||||||
|
{
|
||||||
|
PerformanceInfo info = null;
|
||||||
|
lock(_performances)
|
||||||
|
{
|
||||||
|
if (_performances.ContainsKey(pieceOfCode))
|
||||||
|
info = _performances[pieceOfCode];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info = new PerformanceInfo(pieceOfCode);
|
||||||
|
_performances.Add(pieceOfCode, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
info.Count++;
|
||||||
|
info.Start = TimeCounter.GetStartValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
public static void Finish(string pieceOfCode)
|
||||||
|
{
|
||||||
|
lock (_performances)
|
||||||
|
{
|
||||||
|
if (_performances.ContainsKey(pieceOfCode))
|
||||||
|
{
|
||||||
|
PerformanceInfo info = _performances[pieceOfCode];
|
||||||
|
info.Count++;
|
||||||
|
info.TotalTime += TimeCounter.Finish(info.Start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Reset()
|
||||||
|
{
|
||||||
|
_performances.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateReport()
|
||||||
|
{
|
||||||
|
return GenerateReport(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateReport(string mainPieceOfCode)
|
||||||
|
{
|
||||||
|
if (_performances.ContainsKey(mainPieceOfCode))
|
||||||
|
return GenerateReport(_performances[mainPieceOfCode].TotalTime);
|
||||||
|
else
|
||||||
|
return GenerateReport(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GenerateReport(double totalTime)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
int len = 0;
|
||||||
|
foreach (PerformanceInfo info in Performances)
|
||||||
|
len = Math.Max(info.Name.Length, len);
|
||||||
|
|
||||||
|
sb.AppendLine("Name".PadRight(len) + " Count Total Time, ms Avg. Time, ms Percentage, %");
|
||||||
|
sb.AppendLine("----------------------------------------------------------------------------------------------");
|
||||||
|
foreach (PerformanceInfo info in Performances)
|
||||||
|
{
|
||||||
|
sb.Append(info.Name.PadRight(len));
|
||||||
|
double p = 0;
|
||||||
|
double avgt = 0;
|
||||||
|
if (totalTime != 0)
|
||||||
|
p = info.TotalTime / totalTime;
|
||||||
|
if (info.Count > 0)
|
||||||
|
avgt = info.TotalTime * 1000 / info.Count;
|
||||||
|
string c = info.Count.ToString("0,0").PadRight(20);
|
||||||
|
string tt = (info.TotalTime * 1000).ToString("0,0.00").PadRight(20);
|
||||||
|
string t = avgt.ToString("0.0000").PadRight(20);
|
||||||
|
string sp = (p * 100).ToString("###").PadRight(20);
|
||||||
|
sb.AppendFormat(" " + c + tt + t + sp + "\n");
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
133
LibreHardwareMonitor-0.9.4/Aga.Controls/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.235
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace Aga.Controls.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Aga.Controls.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap check {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("check", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte[] DVSplit {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("DVSplit", resourceCulture);
|
||||||
|
return ((byte[])(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap Folder {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("Folder", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap FolderClosed {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("FolderClosed", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap Leaf {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("Leaf", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte[] loading_icon {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("loading_icon", resourceCulture);
|
||||||
|
return ((byte[])(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap minus {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("minus", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap plus {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("plus", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap uncheck {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("uncheck", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static System.Drawing.Bitmap unknown {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("unknown", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
|
<data name="check" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\check.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="DVSplit" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\DVSplit.cur;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
|
<data name="Folder" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\Folder.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="FolderClosed" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\FolderClosed.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="Leaf" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\Leaf.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="loading_icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\loading_icon;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
|
<data name="minus" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\minus.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="plus" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\plus.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="uncheck" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\uncheck.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="unknown" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\unknown.bmp;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
48
LibreHardwareMonitor-0.9.4/Aga.Controls/ResourceHelper.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
public static class ResourceHelper
|
||||||
|
{
|
||||||
|
// VSpilt Cursor with Innerline (symbolisize hidden column)
|
||||||
|
private static Cursor _dVSplitCursor = GetCursor(Properties.Resources.DVSplit);
|
||||||
|
public static Cursor DVSplitCursor
|
||||||
|
{
|
||||||
|
get { return _dVSplitCursor; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static GifDecoder _loadingIcon = GetGifDecoder(Properties.Resources.loading_icon);
|
||||||
|
public static GifDecoder LoadingIcon
|
||||||
|
{
|
||||||
|
get { return _loadingIcon; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Help function to convert byte[] from resource into Cursor Type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static Cursor GetCursor(byte[] data)
|
||||||
|
{
|
||||||
|
using (MemoryStream s = new MemoryStream(data))
|
||||||
|
return new Cursor(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Help function to convert byte[] from resource into GifDecoder Type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static GifDecoder GetGifDecoder(byte[] data)
|
||||||
|
{
|
||||||
|
using(MemoryStream ms = new MemoryStream(data))
|
||||||
|
return new GifDecoder(ms, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/DVSplit.cur
Normal file
|
After Width: | Height: | Size: 326 B |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/Folder.bmp
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 822 B |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/Leaf.bmp
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/check.bmp
Normal file
|
After Width: | Height: | Size: 574 B |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/loading_icon
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/minus.bmp
Normal file
|
After Width: | Height: | Size: 306 B |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/plus.bmp
Normal file
|
After Width: | Height: | Size: 306 B |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/uncheck.bmp
Normal file
|
After Width: | Height: | Size: 574 B |
BIN
LibreHardwareMonitor-0.9.4/Aga.Controls/Resources/unknown.bmp
Normal file
|
After Width: | Height: | Size: 574 B |
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.ComponentModel.Design;
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
public class StringCollectionEditor : CollectionEditor
|
||||||
|
{
|
||||||
|
public StringCollectionEditor(Type type): base(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Type CreateCollectionItemType()
|
||||||
|
{
|
||||||
|
return typeof(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override object CreateInstance(Type itemType)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
LibreHardwareMonitor-0.9.4/Aga.Controls/TextHelper.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
public static class TextHelper
|
||||||
|
{
|
||||||
|
public static StringAlignment TranslateAligment(HorizontalAlignment alignment)
|
||||||
|
{
|
||||||
|
if (alignment == HorizontalAlignment.Left)
|
||||||
|
return StringAlignment.Near;
|
||||||
|
else if (alignment == HorizontalAlignment.Right)
|
||||||
|
return StringAlignment.Far;
|
||||||
|
else
|
||||||
|
return StringAlignment.Center;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextFormatFlags TranslateAligmentToFlag(HorizontalAlignment alignment)
|
||||||
|
{
|
||||||
|
if (alignment == HorizontalAlignment.Left)
|
||||||
|
return TextFormatFlags.Left;
|
||||||
|
else if (alignment == HorizontalAlignment.Right)
|
||||||
|
return TextFormatFlags.Right;
|
||||||
|
else
|
||||||
|
return TextFormatFlags.HorizontalCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextFormatFlags TranslateTrimmingToFlag(StringTrimming trimming)
|
||||||
|
{
|
||||||
|
if (trimming == StringTrimming.EllipsisCharacter)
|
||||||
|
return TextFormatFlags.EndEllipsis;
|
||||||
|
else if (trimming == StringTrimming.EllipsisPath)
|
||||||
|
return TextFormatFlags.PathEllipsis;
|
||||||
|
if (trimming == StringTrimming.EllipsisWord)
|
||||||
|
return TextFormatFlags.WordEllipsis;
|
||||||
|
if (trimming == StringTrimming.Word)
|
||||||
|
return TextFormatFlags.WordBreak;
|
||||||
|
else
|
||||||
|
return TextFormatFlags.Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
// Stephen Toub
|
||||||
|
// stoub@microsoft.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Threading
|
||||||
|
{
|
||||||
|
public class AbortableThreadPool
|
||||||
|
{
|
||||||
|
private LinkedList<WorkItem> _callbacks = new LinkedList<WorkItem>();
|
||||||
|
private Dictionary<WorkItem, Thread> _threads = new Dictionary<WorkItem, Thread>();
|
||||||
|
|
||||||
|
public WorkItem QueueUserWorkItem(WaitCallback callback)
|
||||||
|
{
|
||||||
|
return QueueUserWorkItem(callback, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItem QueueUserWorkItem(WaitCallback callback, object state)
|
||||||
|
{
|
||||||
|
if (callback == null) throw new ArgumentNullException("callback");
|
||||||
|
|
||||||
|
WorkItem item = new WorkItem(callback, state, ExecutionContext.Capture());
|
||||||
|
lock (_callbacks)
|
||||||
|
{
|
||||||
|
_callbacks.AddLast(item);
|
||||||
|
}
|
||||||
|
ThreadPool.QueueUserWorkItem(new WaitCallback(HandleItem));
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleItem(object ignored)
|
||||||
|
{
|
||||||
|
WorkItem item = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lock (_callbacks)
|
||||||
|
{
|
||||||
|
if (_callbacks.Count > 0)
|
||||||
|
{
|
||||||
|
item = _callbacks.First.Value;
|
||||||
|
_callbacks.RemoveFirst();
|
||||||
|
}
|
||||||
|
if (item == null)
|
||||||
|
return;
|
||||||
|
_threads.Add(item, Thread.CurrentThread);
|
||||||
|
|
||||||
|
}
|
||||||
|
ExecutionContext.Run(item.Context,
|
||||||
|
delegate { item.Callback(item.State); }, null);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
lock (_callbacks)
|
||||||
|
{
|
||||||
|
if (item != null)
|
||||||
|
_threads.Remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMyThread(Thread thread)
|
||||||
|
{
|
||||||
|
lock (_callbacks)
|
||||||
|
{
|
||||||
|
foreach (Thread t in _threads.Values)
|
||||||
|
{
|
||||||
|
if (t == thread)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemStatus Cancel(WorkItem item, bool allowAbort)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
lock (_callbacks)
|
||||||
|
{
|
||||||
|
LinkedListNode<WorkItem> node = _callbacks.Find(item);
|
||||||
|
if (node != null)
|
||||||
|
{
|
||||||
|
_callbacks.Remove(node);
|
||||||
|
return WorkItemStatus.Queued;
|
||||||
|
}
|
||||||
|
else if (_threads.ContainsKey(item))
|
||||||
|
{
|
||||||
|
if (allowAbort)
|
||||||
|
{
|
||||||
|
_threads[item].Abort();
|
||||||
|
_threads.Remove(item);
|
||||||
|
return WorkItemStatus.Aborted;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return WorkItemStatus.Executing;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return WorkItemStatus.Completed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CancelAll(bool allowAbort)
|
||||||
|
{
|
||||||
|
lock (_callbacks)
|
||||||
|
{
|
||||||
|
_callbacks.Clear();
|
||||||
|
if (allowAbort)
|
||||||
|
{
|
||||||
|
foreach (Thread t in _threads.Values)
|
||||||
|
t.Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Threading
|
||||||
|
{
|
||||||
|
public sealed class WorkItem
|
||||||
|
{
|
||||||
|
private WaitCallback _callback;
|
||||||
|
private object _state;
|
||||||
|
private ExecutionContext _ctx;
|
||||||
|
|
||||||
|
internal WorkItem(WaitCallback wc, object state, ExecutionContext ctx)
|
||||||
|
{
|
||||||
|
_callback = wc;
|
||||||
|
_state = state;
|
||||||
|
_ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal WaitCallback Callback
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object State
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal ExecutionContext Context
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _ctx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Threading
|
||||||
|
{
|
||||||
|
public enum WorkItemStatus
|
||||||
|
{
|
||||||
|
Completed,
|
||||||
|
Queued,
|
||||||
|
Executing,
|
||||||
|
Aborted
|
||||||
|
}
|
||||||
|
}
|
||||||
59
LibreHardwareMonitor-0.9.4/Aga.Controls/TimeCounter.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Aga.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// High resolution timer, used to test performance
|
||||||
|
/// </summary>
|
||||||
|
public static class TimeCounter
|
||||||
|
{
|
||||||
|
private static Int64 _start;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start time counting
|
||||||
|
/// </summary>
|
||||||
|
public static void Start()
|
||||||
|
{
|
||||||
|
_start = 0;
|
||||||
|
QueryPerformanceCounter(ref _start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Int64 GetStartValue()
|
||||||
|
{
|
||||||
|
Int64 t = 0;
|
||||||
|
QueryPerformanceCounter(ref t);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finish time counting
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>time in seconds elapsed from Start till Finish </returns>
|
||||||
|
public static double Finish()
|
||||||
|
{
|
||||||
|
return Finish(_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Finish(Int64 start)
|
||||||
|
{
|
||||||
|
Int64 finish = 0;
|
||||||
|
QueryPerformanceCounter(ref finish);
|
||||||
|
|
||||||
|
Int64 freq = 0;
|
||||||
|
QueryPerformanceFrequency(ref freq);
|
||||||
|
return (finish - start) / (double)freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
static extern bool QueryPerformanceCounter(ref Int64 performanceCount);
|
||||||
|
|
||||||
|
[DllImport("Kernel32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
static extern bool QueryPerformanceFrequency(ref Int64 frequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class AutoRowHeightLayout: IRowLayout
|
||||||
|
{
|
||||||
|
private DrawContext _measureContext;
|
||||||
|
private TreeViewAdv _treeView;
|
||||||
|
private List<Rectangle> _rowCache;
|
||||||
|
|
||||||
|
public AutoRowHeightLayout(TreeViewAdv treeView, int rowHeight)
|
||||||
|
{
|
||||||
|
_rowCache = new List<Rectangle>();
|
||||||
|
_treeView = treeView;
|
||||||
|
PreferredRowHeight = rowHeight;
|
||||||
|
_measureContext = new DrawContext();
|
||||||
|
_measureContext.Graphics = Graphics.FromImage(new Bitmap(1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _rowHeight;
|
||||||
|
public int PreferredRowHeight
|
||||||
|
{
|
||||||
|
get { return _rowHeight; }
|
||||||
|
set { _rowHeight = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int PageRowCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_treeView.RowCount == 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pageHeight = _treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight;
|
||||||
|
int y = 0;
|
||||||
|
for (int i = _treeView.RowCount - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
y += GetRowHeight(i);
|
||||||
|
if (y > pageHeight)
|
||||||
|
return Math.Max(0, _treeView.RowCount - 1 - i);
|
||||||
|
}
|
||||||
|
return _treeView.RowCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CurrentPageSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_treeView.RowCount == 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pageHeight = _treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight;
|
||||||
|
int y = 0;
|
||||||
|
for (int i = _treeView.FirstVisibleRow; i < _treeView.RowCount; i++)
|
||||||
|
{
|
||||||
|
y += GetRowHeight(i);
|
||||||
|
if (y > pageHeight)
|
||||||
|
return Math.Max(0, i - _treeView.FirstVisibleRow);
|
||||||
|
}
|
||||||
|
return Math.Max(0, _treeView.RowCount - _treeView.FirstVisibleRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle GetRowBounds(int rowNo)
|
||||||
|
{
|
||||||
|
if (rowNo >= _rowCache.Count)
|
||||||
|
{
|
||||||
|
int count = _rowCache.Count;
|
||||||
|
int y = count > 0 ? _rowCache[count - 1].Bottom : 0;
|
||||||
|
for (int i = count; i <= rowNo; i++)
|
||||||
|
{
|
||||||
|
int height = GetRowHeight(i);
|
||||||
|
_rowCache.Add(new Rectangle(0, y, 0, height));
|
||||||
|
y += height;
|
||||||
|
}
|
||||||
|
if (rowNo < _rowCache.Count - 1)
|
||||||
|
return Rectangle.Empty;
|
||||||
|
}
|
||||||
|
if (rowNo >= 0 && rowNo < _rowCache.Count)
|
||||||
|
return _rowCache[rowNo];
|
||||||
|
else
|
||||||
|
return Rectangle.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetRowHeight(int rowNo)
|
||||||
|
{
|
||||||
|
if (rowNo < _treeView.RowMap.Count)
|
||||||
|
{
|
||||||
|
TreeNodeAdv node = _treeView.RowMap[rowNo];
|
||||||
|
if (node.Height == null)
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
_measureContext.Font = _treeView.Font;
|
||||||
|
foreach (NodeControl nc in _treeView.NodeControls)
|
||||||
|
{
|
||||||
|
int h = nc.GetActualSize(node, _measureContext).Height;
|
||||||
|
if (h > res)
|
||||||
|
res = h;
|
||||||
|
}
|
||||||
|
node.Height = res;
|
||||||
|
}
|
||||||
|
return node.Height.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetRowAt(Point point)
|
||||||
|
{
|
||||||
|
int py = point.Y - _treeView.ColumnHeaderHeight;
|
||||||
|
int y = 0;
|
||||||
|
for (int i = _treeView.FirstVisibleRow; i < _treeView.RowCount; i++)
|
||||||
|
{
|
||||||
|
int h = GetRowHeight(i);
|
||||||
|
if (py >= y && py < y + h)
|
||||||
|
return i;
|
||||||
|
else
|
||||||
|
y += h;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFirstRow(int lastPageRow)
|
||||||
|
{
|
||||||
|
int pageHeight = _treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight;
|
||||||
|
int y = 0;
|
||||||
|
for (int i = lastPageRow; i >= 0; i--)
|
||||||
|
{
|
||||||
|
y += GetRowHeight(i);
|
||||||
|
if (y > pageHeight)
|
||||||
|
return Math.Max(0, i + 1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearCache()
|
||||||
|
{
|
||||||
|
_rowCache.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
84
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/ClassDiagram.cd
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ClassDiagram MajorVersion="1" MinorVersion="1" MembersFormat="FullSignature">
|
||||||
|
<Font Name="Microsoft Sans Serif" Size="8.25" />
|
||||||
|
<Class Name="Aga.Controls.Tree.TreeModel" BaseTypeListCollapsed="true">
|
||||||
|
<Position X="0.5" Y="7" Width="3.75" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\TreeModel.cs</FileName>
|
||||||
|
<HashCode>AAAkgAAAAAAQAGQAAAAAEAAAEAACQAAAUAAAAAAAAQE=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
<Members>
|
||||||
|
<Field Name="_root" Hidden="true" />
|
||||||
|
</Members>
|
||||||
|
<Compartments>
|
||||||
|
<Compartment Name="Fields" Collapsed="true" />
|
||||||
|
</Compartments>
|
||||||
|
<Lollipop Position="0.2" />
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.TreePath">
|
||||||
|
<Position X="4.5" Y="4.25" Width="2" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\TreePath.cs</FileName>
|
||||||
|
<HashCode>GABAAAAAAAACAAAAAAIAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
<Members>
|
||||||
|
<Field Name="_path" Hidden="true" />
|
||||||
|
<Field Name="Empty" Hidden="true" />
|
||||||
|
<Method Name="TreePath" Hidden="true" />
|
||||||
|
</Members>
|
||||||
|
<Compartments>
|
||||||
|
<Compartment Name="Fields" Collapsed="true" />
|
||||||
|
</Compartments>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.Node">
|
||||||
|
<Position X="4.75" Y="7" Width="2.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\Node.cs</FileName>
|
||||||
|
<HashCode>AAAgABAAgCAAAAAAAgAEVAAQAAAQAAAIAAsgCAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
<Members>
|
||||||
|
<Field Name="_checkState" Hidden="true" />
|
||||||
|
<Field Name="_model" Hidden="true" />
|
||||||
|
<Field Name="_nodes" Hidden="true" />
|
||||||
|
<Field Name="_parent" Hidden="true" />
|
||||||
|
<Field Name="_text" Hidden="true" />
|
||||||
|
</Members>
|
||||||
|
<Compartments>
|
||||||
|
<Compartment Name="Fields" Collapsed="true" />
|
||||||
|
</Compartments>
|
||||||
|
<NestedTypes>
|
||||||
|
<Class Name="Aga.Controls.Tree.Node.NodeCollection" Collapsed="true">
|
||||||
|
<TypeIdentifier>
|
||||||
|
<NewMemberFileName>Tree\Node.cs</NewMemberFileName>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
</NestedTypes>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeControl">
|
||||||
|
<Position X="0.5" Y="0.5" Width="3.75" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeControl.cs</FileName>
|
||||||
|
<HashCode>AAAAAAAAgAAAgsIAAAhAQAAwAAAAEAAAAEAIAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
<Members>
|
||||||
|
<Field Name="_column" Hidden="true" />
|
||||||
|
<Field Name="_parent" Hidden="true" />
|
||||||
|
<Field Name="_toolTipProvider" Hidden="true" />
|
||||||
|
<Method Name="AssignParent" Hidden="true" />
|
||||||
|
</Members>
|
||||||
|
</Class>
|
||||||
|
<Interface Name="Aga.Controls.Tree.ITreeModel">
|
||||||
|
<Position X="0.5" Y="4.25" Width="3.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\ITreeModel.cs</FileName>
|
||||||
|
<HashCode>AAAEAAAAAAAAAEQAAAAAEAAAEAAAQAAAAAAAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Interface>
|
||||||
|
<Interface Name="Aga.Controls.Tree.IToolTipProvider">
|
||||||
|
<Position X="4.5" Y="0.5" Width="2.75" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\IToolTipProvider.cs</FileName>
|
||||||
|
<HashCode>AAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Interface>
|
||||||
|
</ClassDiagram>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
/*internal class ColumnCollection: Collection<Column>
|
||||||
|
{
|
||||||
|
public int TotalWidth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
foreach (Column c in Items)
|
||||||
|
res += c.Width;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
60
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/DrawContext.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public struct DrawContext
|
||||||
|
{
|
||||||
|
private Graphics _graphics;
|
||||||
|
public Graphics Graphics
|
||||||
|
{
|
||||||
|
get { return _graphics; }
|
||||||
|
set { _graphics = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle _bounds;
|
||||||
|
public Rectangle Bounds
|
||||||
|
{
|
||||||
|
get { return _bounds; }
|
||||||
|
set { _bounds = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Font _font;
|
||||||
|
public Font Font
|
||||||
|
{
|
||||||
|
get { return _font; }
|
||||||
|
set { _font = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private DrawSelectionMode _drawSelection;
|
||||||
|
public DrawSelectionMode DrawSelection
|
||||||
|
{
|
||||||
|
get { return _drawSelection; }
|
||||||
|
set { _drawSelection = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _drawFocus;
|
||||||
|
public bool DrawFocus
|
||||||
|
{
|
||||||
|
get { return _drawFocus; }
|
||||||
|
set { _drawFocus = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeControl _currentEditorOwner;
|
||||||
|
public NodeControl CurrentEditorOwner
|
||||||
|
{
|
||||||
|
get { return _currentEditorOwner; }
|
||||||
|
set { _currentEditorOwner = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _enabled;
|
||||||
|
public bool Enabled
|
||||||
|
{
|
||||||
|
get { return _enabled; }
|
||||||
|
set { _enabled = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class DropNodeValidatingEventArgs: EventArgs
|
||||||
|
{
|
||||||
|
Point _point;
|
||||||
|
TreeNodeAdv _node;
|
||||||
|
|
||||||
|
public DropNodeValidatingEventArgs(Point point, TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
_point = point;
|
||||||
|
_node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point Point
|
||||||
|
{
|
||||||
|
get { return _point; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeNodeAdv Node
|
||||||
|
{
|
||||||
|
get { return _node; }
|
||||||
|
set { _node = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/DropPosition.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public struct DropPosition
|
||||||
|
{
|
||||||
|
private TreeNodeAdv _node;
|
||||||
|
public TreeNodeAdv Node
|
||||||
|
{
|
||||||
|
get { return _node; }
|
||||||
|
set { _node = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodePosition _position;
|
||||||
|
public NodePosition Position
|
||||||
|
{
|
||||||
|
get { return _position; }
|
||||||
|
set { _position = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public struct EditorContext
|
||||||
|
{
|
||||||
|
private TreeNodeAdv _currentNode;
|
||||||
|
public TreeNodeAdv CurrentNode
|
||||||
|
{
|
||||||
|
get { return _currentNode; }
|
||||||
|
set { _currentNode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Control _editor;
|
||||||
|
public Control Editor
|
||||||
|
{
|
||||||
|
get { return _editor; }
|
||||||
|
set { _editor = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeControl _owner;
|
||||||
|
public NodeControl Owner
|
||||||
|
{
|
||||||
|
get { return _owner; }
|
||||||
|
set { _owner = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle _bounds;
|
||||||
|
public Rectangle Bounds
|
||||||
|
{
|
||||||
|
get { return _bounds; }
|
||||||
|
set { _bounds = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private DrawContext _drawContext;
|
||||||
|
public DrawContext DrawContext
|
||||||
|
{
|
||||||
|
get { return _drawContext; }
|
||||||
|
set { _drawContext = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/Enums.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public enum DrawSelectionMode
|
||||||
|
{
|
||||||
|
None, Active, Inactive, FullRowSelect
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TreeSelectionMode
|
||||||
|
{
|
||||||
|
Single, Multi, MultiSameParent
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum NodePosition
|
||||||
|
{
|
||||||
|
Inside, Before, After
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VerticalAlignment
|
||||||
|
{
|
||||||
|
Top, Bottom, Center
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum IncrementalSearchMode
|
||||||
|
{
|
||||||
|
None, Standard, Continuous
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum GridLineStyle
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Horizontal = 1,
|
||||||
|
Vertical = 2,
|
||||||
|
HorizontalAndVertical = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ImageScaleMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Don't scale
|
||||||
|
/// </summary>
|
||||||
|
Clip,
|
||||||
|
/// <summary>
|
||||||
|
/// Scales image to fit the display rectangle, aspect ratio is not fixed.
|
||||||
|
/// </summary>
|
||||||
|
Fit,
|
||||||
|
/// <summary>
|
||||||
|
/// Scales image down if it is larger than display rectangle, taking aspect ratio into account
|
||||||
|
/// </summary>
|
||||||
|
ScaleDown,
|
||||||
|
/// <summary>
|
||||||
|
/// Scales image up if it is smaller than display rectangle, taking aspect ratio into account
|
||||||
|
/// </summary>
|
||||||
|
ScaleUp,
|
||||||
|
/// <summary>
|
||||||
|
/// Scales image to match the display rectangle, taking aspect ratio into account
|
||||||
|
/// </summary>
|
||||||
|
AlwaysScale,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class FixedRowHeightLayout : IRowLayout
|
||||||
|
{
|
||||||
|
private TreeViewAdv _treeView;
|
||||||
|
|
||||||
|
public FixedRowHeightLayout(TreeViewAdv treeView, int rowHeight)
|
||||||
|
{
|
||||||
|
_treeView = treeView;
|
||||||
|
PreferredRowHeight = rowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _rowHeight;
|
||||||
|
public int PreferredRowHeight
|
||||||
|
{
|
||||||
|
get { return _rowHeight; }
|
||||||
|
set { _rowHeight = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle GetRowBounds(int rowNo)
|
||||||
|
{
|
||||||
|
return new Rectangle(0, rowNo * _rowHeight, 0, _rowHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int PageRowCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Math.Max((_treeView.DisplayRectangle.Height - _treeView.ColumnHeaderHeight) / _rowHeight, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CurrentPageSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return PageRowCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetRowAt(Point point)
|
||||||
|
{
|
||||||
|
point = new Point(point.X, point.Y + (_treeView.FirstVisibleRow * _rowHeight) - _treeView.ColumnHeaderHeight);
|
||||||
|
return point.Y / _rowHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFirstRow(int lastPageRow)
|
||||||
|
{
|
||||||
|
return Math.Max(0, lastPageRow - PageRowCount + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearCache()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/IRowLayout.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal interface IRowLayout
|
||||||
|
{
|
||||||
|
int PreferredRowHeight
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PageRowCount
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CurrentPageSize
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle GetRowBounds(int rowNo);
|
||||||
|
|
||||||
|
int GetRowAt(Point point);
|
||||||
|
|
||||||
|
int GetFirstRow(int lastPageRow);
|
||||||
|
|
||||||
|
void ClearCache();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public interface IToolTipProvider
|
||||||
|
{
|
||||||
|
string GetToolTip(TreeNodeAdv node, NodeControl nodeControl);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/ITreeModel.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public interface ITreeModel
|
||||||
|
{
|
||||||
|
IEnumerable GetChildren(TreePath treePath);
|
||||||
|
bool IsLeaf(TreePath treePath);
|
||||||
|
|
||||||
|
event EventHandler<TreeModelEventArgs> NodesChanged;
|
||||||
|
event EventHandler<TreeModelEventArgs> NodesInserted;
|
||||||
|
event EventHandler<TreeModelEventArgs> NodesRemoved;
|
||||||
|
event EventHandler<TreePathEventArgs> StructureChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class IncrementalSearch
|
||||||
|
{
|
||||||
|
private const int SearchTimeout = 300; //end of incremental search timeot in msec
|
||||||
|
|
||||||
|
private TreeViewAdv _tree;
|
||||||
|
private TreeNodeAdv _currentNode;
|
||||||
|
private string _searchString = "";
|
||||||
|
private DateTime _lastKeyPressed = DateTime.Now;
|
||||||
|
|
||||||
|
public IncrementalSearch(TreeViewAdv tree)
|
||||||
|
{
|
||||||
|
_tree = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Search(Char value)
|
||||||
|
{
|
||||||
|
if (!Char.IsControl(value))
|
||||||
|
{
|
||||||
|
Char ch = Char.ToLowerInvariant(value);
|
||||||
|
DateTime dt = DateTime.Now;
|
||||||
|
TimeSpan ts = dt - _lastKeyPressed;
|
||||||
|
_lastKeyPressed = dt;
|
||||||
|
if (ts.TotalMilliseconds < SearchTimeout)
|
||||||
|
{
|
||||||
|
if (_searchString == value.ToString())
|
||||||
|
FirstCharSearch(ch);
|
||||||
|
else
|
||||||
|
ContinuousSearch(ch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FirstCharSearch(ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ContinuousSearch(Char value)
|
||||||
|
{
|
||||||
|
if (value == ' ' && String.IsNullOrEmpty(_searchString))
|
||||||
|
return; //Ingnore leading space
|
||||||
|
|
||||||
|
_searchString += value;
|
||||||
|
DoContinuousSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FirstCharSearch(Char value)
|
||||||
|
{
|
||||||
|
if (value == ' ')
|
||||||
|
return;
|
||||||
|
|
||||||
|
_searchString = value.ToString();
|
||||||
|
TreeNodeAdv node = null;
|
||||||
|
if (_tree.SelectedNode != null)
|
||||||
|
node = _tree.SelectedNode.NextVisibleNode;
|
||||||
|
if (node == null)
|
||||||
|
node = _tree.Root.NextVisibleNode;
|
||||||
|
|
||||||
|
if (node != null)
|
||||||
|
foreach (string label in IterateNodeLabels(node))
|
||||||
|
{
|
||||||
|
if (label.StartsWith(_searchString))
|
||||||
|
{
|
||||||
|
_tree.SelectedNode = _currentNode;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void EndSearch()
|
||||||
|
{
|
||||||
|
_currentNode = null;
|
||||||
|
_searchString = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IEnumerable<string> IterateNodeLabels(TreeNodeAdv start)
|
||||||
|
{
|
||||||
|
_currentNode = start;
|
||||||
|
while(_currentNode != null)
|
||||||
|
{
|
||||||
|
foreach (string label in GetNodeLabels(_currentNode))
|
||||||
|
yield return label;
|
||||||
|
|
||||||
|
_currentNode = _currentNode.NextVisibleNode;
|
||||||
|
if (_currentNode == null)
|
||||||
|
_currentNode = _tree.Root;
|
||||||
|
|
||||||
|
if (start == _currentNode)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> GetNodeLabels(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
foreach (NodeControl nc in _tree.NodeControls)
|
||||||
|
{
|
||||||
|
BindableControl bc = nc as BindableControl;
|
||||||
|
if (bc != null && bc.IncrementalSearchEnabled)
|
||||||
|
{
|
||||||
|
object obj = bc.GetValue(node);
|
||||||
|
if (obj != null)
|
||||||
|
yield return obj.ToString().ToLowerInvariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool DoContinuousSearch()
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
if (!String.IsNullOrEmpty(_searchString))
|
||||||
|
{
|
||||||
|
TreeNodeAdv node = null;
|
||||||
|
if (_tree.SelectedNode != null)
|
||||||
|
node = _tree.SelectedNode;
|
||||||
|
if (node == null)
|
||||||
|
node = _tree.Root.NextVisibleNode;
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(_searchString))
|
||||||
|
{
|
||||||
|
foreach (string label in IterateNodeLabels(node))
|
||||||
|
{
|
||||||
|
if (label.StartsWith(_searchString))
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
_tree.SelectedNode = _currentNode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class ClickColumnState : ColumnState
|
||||||
|
{
|
||||||
|
private Point _location;
|
||||||
|
|
||||||
|
public ClickColumnState(TreeViewAdv tree, TreeColumn column, Point location)
|
||||||
|
: base(tree, column)
|
||||||
|
{
|
||||||
|
_location = location;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool MouseMove(MouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (TreeViewAdv.Dist(_location, args.Location) > TreeViewAdv.ItemDragSensivity
|
||||||
|
&& Tree.AllowColumnReorder)
|
||||||
|
{
|
||||||
|
Tree.Input = new ReorderColumnState(Tree, Column, args.Location);
|
||||||
|
Tree.UpdateView();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
Tree.ChangeInput();
|
||||||
|
Tree.UpdateView();
|
||||||
|
Tree.OnColumnClicked(Column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal abstract class ColumnState : InputState
|
||||||
|
{
|
||||||
|
private TreeColumn _column;
|
||||||
|
public TreeColumn Column
|
||||||
|
{
|
||||||
|
get { return _column; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColumnState(TreeViewAdv tree, TreeColumn column)
|
||||||
|
: base(tree)
|
||||||
|
{
|
||||||
|
_column = column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal abstract class InputState
|
||||||
|
{
|
||||||
|
private TreeViewAdv _tree;
|
||||||
|
|
||||||
|
public TreeViewAdv Tree
|
||||||
|
{
|
||||||
|
get { return _tree; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputState(TreeViewAdv tree)
|
||||||
|
{
|
||||||
|
_tree = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void KeyDown(System.Windows.Forms.KeyEventArgs args);
|
||||||
|
public abstract void MouseDown(TreeNodeAdvMouseEventArgs args);
|
||||||
|
public abstract void MouseUp(TreeNodeAdvMouseEventArgs args);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// handle OnMouseMove event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
/// <returns>true if event was handled and should be dispatched</returns>
|
||||||
|
public virtual bool MouseMove(MouseEventArgs args)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class InputWithControl: NormalInputState
|
||||||
|
{
|
||||||
|
public InputWithControl(TreeViewAdv tree): base(tree)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoMouseOperation(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (Tree.SelectionMode == TreeSelectionMode.Single)
|
||||||
|
{
|
||||||
|
base.DoMouseOperation(args);
|
||||||
|
}
|
||||||
|
else if (CanSelect(args.Node))
|
||||||
|
{
|
||||||
|
args.Node.IsSelected = !args.Node.IsSelected;
|
||||||
|
Tree.SelectionStart = args.Node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void MouseDownAtEmptySpace(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class InputWithShift: NormalInputState
|
||||||
|
{
|
||||||
|
public InputWithShift(TreeViewAdv tree): base(tree)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FocusRow(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
Tree.SuspendSelectionEvent = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Tree.SelectionMode == TreeSelectionMode.Single || Tree.SelectionStart == null)
|
||||||
|
base.FocusRow(node);
|
||||||
|
else if (CanSelect(node))
|
||||||
|
{
|
||||||
|
SelectAllFromStart(node);
|
||||||
|
Tree.CurrentNode = node;
|
||||||
|
Tree.ScrollTo(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Tree.SuspendSelectionEvent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoMouseOperation(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (Tree.SelectionMode == TreeSelectionMode.Single || Tree.SelectionStart == null)
|
||||||
|
{
|
||||||
|
base.DoMouseOperation(args);
|
||||||
|
}
|
||||||
|
else if (CanSelect(args.Node))
|
||||||
|
{
|
||||||
|
Tree.SuspendSelectionEvent = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SelectAllFromStart(args.Node);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Tree.SuspendSelectionEvent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void MouseDownAtEmptySpace(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectAllFromStart(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
Tree.ClearSelectionInternal();
|
||||||
|
int a = node.Row;
|
||||||
|
int b = Tree.SelectionStart.Row;
|
||||||
|
for (int i = Math.Min(a, b); i <= Math.Max(a, b); i++)
|
||||||
|
{
|
||||||
|
if (Tree.SelectionMode == TreeSelectionMode.Multi || Tree.RowMap[i].Parent == node.Parent)
|
||||||
|
Tree.RowMap[i].IsSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class NormalInputState : InputState
|
||||||
|
{
|
||||||
|
private bool _mouseDownFlag = false;
|
||||||
|
|
||||||
|
public NormalInputState(TreeViewAdv tree) : base(tree)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
if (Tree.CurrentNode == null && Tree.Root.Nodes.Count > 0)
|
||||||
|
Tree.CurrentNode = Tree.Root.Nodes[0];
|
||||||
|
|
||||||
|
if (Tree.CurrentNode != null)
|
||||||
|
{
|
||||||
|
switch (args.KeyCode)
|
||||||
|
{
|
||||||
|
case Keys.Right:
|
||||||
|
if (!Tree.CurrentNode.IsExpanded)
|
||||||
|
Tree.CurrentNode.IsExpanded = true;
|
||||||
|
else if (Tree.CurrentNode.Nodes.Count > 0)
|
||||||
|
Tree.SelectedNode = Tree.CurrentNode.Nodes[0];
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.Left:
|
||||||
|
if (Tree.CurrentNode.IsExpanded)
|
||||||
|
Tree.CurrentNode.IsExpanded = false;
|
||||||
|
else if (Tree.CurrentNode.Parent != Tree.Root)
|
||||||
|
Tree.SelectedNode = Tree.CurrentNode.Parent;
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.Down:
|
||||||
|
NavigateForward(1);
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.Up:
|
||||||
|
NavigateBackward(1);
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.PageDown:
|
||||||
|
NavigateForward(Math.Max(1, Tree.CurrentPageSize - 1));
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.PageUp:
|
||||||
|
NavigateBackward(Math.Max(1, Tree.CurrentPageSize - 1));
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.Home:
|
||||||
|
if (Tree.RowMap.Count > 0)
|
||||||
|
FocusRow(Tree.RowMap[0]);
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.End:
|
||||||
|
if (Tree.RowMap.Count > 0)
|
||||||
|
FocusRow(Tree.RowMap[Tree.RowMap.Count-1]);
|
||||||
|
args.Handled = true;
|
||||||
|
break;
|
||||||
|
case Keys.Subtract:
|
||||||
|
Tree.CurrentNode.Collapse();
|
||||||
|
args.Handled = true;
|
||||||
|
args.SuppressKeyPress = true;
|
||||||
|
break;
|
||||||
|
case Keys.Add:
|
||||||
|
Tree.CurrentNode.Expand();
|
||||||
|
args.Handled = true;
|
||||||
|
args.SuppressKeyPress = true;
|
||||||
|
break;
|
||||||
|
case Keys.Multiply:
|
||||||
|
Tree.CurrentNode.ExpandAll();
|
||||||
|
args.Handled = true;
|
||||||
|
args.SuppressKeyPress = true;
|
||||||
|
break;
|
||||||
|
case Keys.A:
|
||||||
|
if (args.Modifiers == Keys.Control)
|
||||||
|
Tree.SelectAllNodes();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Node != null)
|
||||||
|
{
|
||||||
|
Tree.ItemDragMode = true;
|
||||||
|
Tree.ItemDragStart = args.Location;
|
||||||
|
|
||||||
|
if (args.Button == MouseButtons.Left || args.Button == MouseButtons.Right)
|
||||||
|
{
|
||||||
|
Tree.BeginUpdate();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Tree.CurrentNode = args.Node;
|
||||||
|
if (args.Node.IsSelected)
|
||||||
|
_mouseDownFlag = true;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_mouseDownFlag = false;
|
||||||
|
DoMouseOperation(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Tree.EndUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Tree.ItemDragMode = false;
|
||||||
|
MouseDownAtEmptySpace(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
Tree.ItemDragMode = false;
|
||||||
|
if (_mouseDownFlag && args.Node != null)
|
||||||
|
{
|
||||||
|
if (args.Button == MouseButtons.Left)
|
||||||
|
DoMouseOperation(args);
|
||||||
|
else if (args.Button == MouseButtons.Right)
|
||||||
|
Tree.CurrentNode = args.Node;
|
||||||
|
}
|
||||||
|
_mouseDownFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void NavigateBackward(int n)
|
||||||
|
{
|
||||||
|
int row = Math.Max(Tree.CurrentNode.Row - n, 0);
|
||||||
|
if (row != Tree.CurrentNode.Row)
|
||||||
|
FocusRow(Tree.RowMap[row]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NavigateForward(int n)
|
||||||
|
{
|
||||||
|
int row = Math.Min(Tree.CurrentNode.Row + n, Tree.RowCount - 1);
|
||||||
|
if (row != Tree.CurrentNode.Row)
|
||||||
|
FocusRow(Tree.RowMap[row]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void MouseDownAtEmptySpace(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
Tree.ClearSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void FocusRow(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
Tree.SuspendSelectionEvent = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Tree.ClearSelectionInternal();
|
||||||
|
Tree.CurrentNode = node;
|
||||||
|
Tree.SelectionStart = node;
|
||||||
|
node.IsSelected = true;
|
||||||
|
Tree.ScrollTo(node);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Tree.SuspendSelectionEvent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool CanSelect(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
if (Tree.SelectionMode == TreeSelectionMode.MultiSameParent)
|
||||||
|
{
|
||||||
|
return (Tree.SelectionStart == null || node.Parent == Tree.SelectionStart.Parent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void DoMouseOperation(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (Tree.SelectedNodes.Count == 1 && args.Node != null && args.Node.IsSelected)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Tree.SuspendSelectionEvent = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Tree.ClearSelectionInternal();
|
||||||
|
if (args.Node != null)
|
||||||
|
args.Node.IsSelected = true;
|
||||||
|
Tree.SelectionStart = args.Node;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Tree.SuspendSelectionEvent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class ReorderColumnState : ColumnState
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private Point _location;
|
||||||
|
public Point Location
|
||||||
|
{
|
||||||
|
get { return _location; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bitmap _ghostImage;
|
||||||
|
public Bitmap GhostImage
|
||||||
|
{
|
||||||
|
get { return _ghostImage; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeColumn _dropColumn;
|
||||||
|
public TreeColumn DropColumn
|
||||||
|
{
|
||||||
|
get { return _dropColumn; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _dragOffset;
|
||||||
|
public int DragOffset
|
||||||
|
{
|
||||||
|
get { return _dragOffset; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public ReorderColumnState(TreeViewAdv tree, TreeColumn column, Point initialMouseLocation)
|
||||||
|
: base(tree, column)
|
||||||
|
{
|
||||||
|
_location = new Point(initialMouseLocation.X + Tree.OffsetX, 0);
|
||||||
|
_dragOffset = tree.GetColumnX(column) - initialMouseLocation.X;
|
||||||
|
_ghostImage = column.CreateGhostImage(new Rectangle(0, 0, column.Width, tree.ColumnHeaderHeight), tree.Font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
if (args.KeyCode == Keys.Escape)
|
||||||
|
FinishResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
FinishResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool MouseMove(MouseEventArgs args)
|
||||||
|
{
|
||||||
|
_dropColumn = null;
|
||||||
|
_location = new Point(args.X + Tree.OffsetX, 0);
|
||||||
|
int x = 0;
|
||||||
|
foreach (TreeColumn c in Tree.Columns)
|
||||||
|
{
|
||||||
|
if (c.IsVisible)
|
||||||
|
{
|
||||||
|
if (_location.X < x + c.Width / 2)
|
||||||
|
{
|
||||||
|
_dropColumn = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
x += c.Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tree.UpdateHeaders();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FinishResize()
|
||||||
|
{
|
||||||
|
Tree.ChangeInput();
|
||||||
|
if (Column == DropColumn)
|
||||||
|
Tree.UpdateView();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Tree.Columns.Remove(Column);
|
||||||
|
if (DropColumn == null)
|
||||||
|
Tree.Columns.Add(Column);
|
||||||
|
else
|
||||||
|
Tree.Columns.Insert(Tree.Columns.IndexOf(DropColumn), Column);
|
||||||
|
|
||||||
|
Tree.OnColumnReordered(Column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Security.Permissions;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class ResizeColumnState: ColumnState
|
||||||
|
{
|
||||||
|
private Point _initLocation;
|
||||||
|
private int _initWidth;
|
||||||
|
|
||||||
|
public ResizeColumnState(TreeViewAdv tree, TreeColumn column, Point p)
|
||||||
|
: base(tree, column)
|
||||||
|
{
|
||||||
|
_initLocation = p;
|
||||||
|
_initWidth = column.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
if (args.KeyCode == Keys.Escape)
|
||||||
|
FinishResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
FinishResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void FinishResize()
|
||||||
|
{
|
||||||
|
Tree.ChangeInput();
|
||||||
|
Tree.FullUpdate();
|
||||||
|
Tree.OnColumnWidthChanged(Column);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool MouseMove(MouseEventArgs args)
|
||||||
|
{
|
||||||
|
Column.Width = _initWidth + args.Location.X - _initLocation.X;
|
||||||
|
Tree.UpdateView();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
Tree.AutoSizeColumn(Column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/ListModel.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class ListModel : TreeModelBase
|
||||||
|
{
|
||||||
|
private IList _list;
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _list.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListModel()
|
||||||
|
{
|
||||||
|
_list = new List<object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ListModel(IList list)
|
||||||
|
{
|
||||||
|
_list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable GetChildren(TreePath treePath)
|
||||||
|
{
|
||||||
|
return _list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsLeaf(TreePath treePath)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange(IEnumerable items)
|
||||||
|
{
|
||||||
|
foreach (object obj in items)
|
||||||
|
_list.Add(obj);
|
||||||
|
OnStructureChanged(new TreePathEventArgs(TreePath.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(object item)
|
||||||
|
{
|
||||||
|
_list.Add(item);
|
||||||
|
OnNodesInserted(new TreeModelEventArgs(TreePath.Empty, new int[] { _list.Count - 1 }, new object[] { item }));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_list.Clear();
|
||||||
|
OnStructureChanged(new TreePathEventArgs(TreePath.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal static class NativeMethods
|
||||||
|
{
|
||||||
|
public const int DCX_WINDOW = 0x01;
|
||||||
|
public const int DCX_CACHE = 0x02;
|
||||||
|
public const int DCX_NORESETATTRS = 0x04;
|
||||||
|
public const int DCX_CLIPCHILDREN = 0x08;
|
||||||
|
public const int DCX_CLIPSIBLINGS = 0x10;
|
||||||
|
public const int DCX_PARENTCLIP = 0x20;
|
||||||
|
public const int DCX_EXCLUDERGN = 0x40;
|
||||||
|
public const int DCX_INTERSECTRGN = 0x80;
|
||||||
|
public const int DCX_EXCLUDEUPDATE = 0x100;
|
||||||
|
public const int DCX_INTERSECTUPDATE = 0x200;
|
||||||
|
public const int DCX_LOCKWINDOWUPDATE = 0x400;
|
||||||
|
public const int DCX_VALIDATE = 0x200000;
|
||||||
|
|
||||||
|
public const int WM_THEMECHANGED = 0x031A;
|
||||||
|
public const int WM_NCPAINT = 0x85;
|
||||||
|
public const int WM_NCCALCSIZE = 0x83;
|
||||||
|
|
||||||
|
public const int WS_BORDER = 0x800000;
|
||||||
|
public const int WS_EX_CLIENTEDGE = 0x200;
|
||||||
|
|
||||||
|
public const int WVR_HREDRAW = 0x100;
|
||||||
|
public const int WVR_VREDRAW = 0x200;
|
||||||
|
public const int WVR_REDRAW = (WVR_HREDRAW | WVR_VREDRAW);
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct NCCALCSIZE_PARAMS
|
||||||
|
{
|
||||||
|
public RECT rgrc0, rgrc1, rgrc2;
|
||||||
|
public IntPtr lppos;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct RECT
|
||||||
|
{
|
||||||
|
public int Left;
|
||||||
|
public int Top;
|
||||||
|
public int Right;
|
||||||
|
public int Bottom;
|
||||||
|
|
||||||
|
public static RECT FromRectangle(Rectangle rectangle)
|
||||||
|
{
|
||||||
|
RECT result = new RECT();
|
||||||
|
result.Left = rectangle.Left;
|
||||||
|
result.Top = rectangle.Top;
|
||||||
|
result.Right = rectangle.Right;
|
||||||
|
result.Bottom = rectangle.Bottom;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle ToRectangle()
|
||||||
|
{
|
||||||
|
return new Rectangle(Left, Top, Right - Left, Bottom - Top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip, int flags);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
257
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/Node.cs
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class Node
|
||||||
|
{
|
||||||
|
#region NodeCollection
|
||||||
|
|
||||||
|
private class NodeCollection : Collection<Node>
|
||||||
|
{
|
||||||
|
private Node _owner;
|
||||||
|
|
||||||
|
public NodeCollection(Node owner)
|
||||||
|
{
|
||||||
|
_owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ClearItems()
|
||||||
|
{
|
||||||
|
while (this.Count != 0)
|
||||||
|
this.RemoveAt(this.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InsertItem(int index, Node item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
|
||||||
|
if (item.Parent != _owner)
|
||||||
|
{
|
||||||
|
if (item.Parent != null)
|
||||||
|
item.Parent.Nodes.Remove(item);
|
||||||
|
item._parent = _owner;
|
||||||
|
item._index = index;
|
||||||
|
for (int i = index; i < Count; i++)
|
||||||
|
this[i]._index++;
|
||||||
|
base.InsertItem(index, item);
|
||||||
|
|
||||||
|
TreeModel model = _owner.FindModel();
|
||||||
|
if (model != null)
|
||||||
|
model.OnNodeInserted(_owner, index, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RemoveItem(int index)
|
||||||
|
{
|
||||||
|
Node item = this[index];
|
||||||
|
item._parent = null;
|
||||||
|
item._index = -1;
|
||||||
|
for (int i = index + 1; i < Count; i++)
|
||||||
|
this[i]._index--;
|
||||||
|
base.RemoveItem(index);
|
||||||
|
|
||||||
|
TreeModel model = _owner.FindModel();
|
||||||
|
if (model != null)
|
||||||
|
model.OnNodeRemoved(_owner, index, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetItem(int index, Node item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
|
||||||
|
RemoveAt(index);
|
||||||
|
InsertItem(index, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private TreeModel _model;
|
||||||
|
internal TreeModel Model
|
||||||
|
{
|
||||||
|
get { return _model; }
|
||||||
|
set { _model = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeCollection _nodes;
|
||||||
|
public Collection<Node> Nodes
|
||||||
|
{
|
||||||
|
get { return _nodes; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node _parent;
|
||||||
|
public Node Parent
|
||||||
|
{
|
||||||
|
get { return _parent; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _parent)
|
||||||
|
{
|
||||||
|
if (_parent != null)
|
||||||
|
_parent.Nodes.Remove(this);
|
||||||
|
|
||||||
|
if (value != null)
|
||||||
|
value.Nodes.Add(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _index = -1;
|
||||||
|
public int Index
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node PreviousNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int index = Index;
|
||||||
|
if (index > 0)
|
||||||
|
return _parent.Nodes[index - 1];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node NextNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int index = Index;
|
||||||
|
if (index >= 0 && index < _parent.Nodes.Count - 1)
|
||||||
|
return _parent.Nodes[index + 1];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _text;
|
||||||
|
public virtual string Text
|
||||||
|
{
|
||||||
|
get { return _text; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_text != value)
|
||||||
|
{
|
||||||
|
_text = value;
|
||||||
|
NotifyModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckState _checkState;
|
||||||
|
public virtual CheckState CheckState
|
||||||
|
{
|
||||||
|
get { return _checkState; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_checkState != value)
|
||||||
|
{
|
||||||
|
_checkState = value;
|
||||||
|
NotifyModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Image _image;
|
||||||
|
public Image Image
|
||||||
|
{
|
||||||
|
get { return _image; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_image != value)
|
||||||
|
{
|
||||||
|
_image = value;
|
||||||
|
NotifyModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object _tag;
|
||||||
|
public object Tag
|
||||||
|
{
|
||||||
|
get { return _tag; }
|
||||||
|
set { _tag = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsChecked
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return CheckState != CheckState.Unchecked;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
CheckState = CheckState.Checked;
|
||||||
|
else
|
||||||
|
CheckState = CheckState.Unchecked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool IsLeaf
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public Node()
|
||||||
|
: this(string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node(string text)
|
||||||
|
{
|
||||||
|
_text = text;
|
||||||
|
_nodes = new NodeCollection(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeModel FindModel()
|
||||||
|
{
|
||||||
|
Node node = this;
|
||||||
|
while (node != null)
|
||||||
|
{
|
||||||
|
if (node.Model != null)
|
||||||
|
return node.Model;
|
||||||
|
node = node.Parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void NotifyModel()
|
||||||
|
{
|
||||||
|
TreeModel model = FindModel();
|
||||||
|
if (model != null && Parent != null)
|
||||||
|
{
|
||||||
|
TreePath path = model.GetPath(Parent);
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
TreeModelEventArgs args = new TreeModelEventArgs(path, new int[] { Index }, new object[] { this });
|
||||||
|
model.OnNodesChanged(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public struct NodeControlInfo
|
||||||
|
{
|
||||||
|
public static readonly NodeControlInfo Empty = new NodeControlInfo(null, Rectangle.Empty, null);
|
||||||
|
|
||||||
|
private NodeControl _control;
|
||||||
|
public NodeControl Control
|
||||||
|
{
|
||||||
|
get { return _control; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle _bounds;
|
||||||
|
public Rectangle Bounds
|
||||||
|
{
|
||||||
|
get { return _bounds; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNodeAdv _node;
|
||||||
|
public TreeNodeAdv Node
|
||||||
|
{
|
||||||
|
get { return _node; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeControlInfo(NodeControl control, Rectangle bounds, TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
_control = control;
|
||||||
|
_bounds = bounds;
|
||||||
|
_node = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,314 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public abstract class BaseTextControl : EditableControl
|
||||||
|
{
|
||||||
|
private TextFormatFlags _baseFormatFlags;
|
||||||
|
private TextFormatFlags _formatFlags;
|
||||||
|
private Pen _focusPen;
|
||||||
|
private StringFormat _format;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private Font _font = null;
|
||||||
|
public Font Font
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_font == null)
|
||||||
|
return Control.DefaultFont;
|
||||||
|
else
|
||||||
|
return _font;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == Control.DefaultFont)
|
||||||
|
_font = null;
|
||||||
|
else
|
||||||
|
_font = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool ShouldSerializeFont()
|
||||||
|
{
|
||||||
|
return (_font != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private HorizontalAlignment _textAlign = HorizontalAlignment.Left;
|
||||||
|
[DefaultValue(HorizontalAlignment.Left)]
|
||||||
|
public HorizontalAlignment TextAlign
|
||||||
|
{
|
||||||
|
get { return _textAlign; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_textAlign = value;
|
||||||
|
SetFormatFlags();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringTrimming _trimming = StringTrimming.None;
|
||||||
|
[DefaultValue(StringTrimming.None)]
|
||||||
|
public StringTrimming Trimming
|
||||||
|
{
|
||||||
|
get { return _trimming; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_trimming = value;
|
||||||
|
SetFormatFlags();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _displayHiddenContentInToolTip = true;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool DisplayHiddenContentInToolTip
|
||||||
|
{
|
||||||
|
get { return _displayHiddenContentInToolTip; }
|
||||||
|
set { _displayHiddenContentInToolTip = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _useCompatibleTextRendering = false;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool UseCompatibleTextRendering
|
||||||
|
{
|
||||||
|
get { return _useCompatibleTextRendering; }
|
||||||
|
set { _useCompatibleTextRendering = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool TrimMultiLine
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
protected BaseTextControl()
|
||||||
|
{
|
||||||
|
IncrementalSearchEnabled = true;
|
||||||
|
_focusPen = new Pen(Color.Black);
|
||||||
|
_focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
|
||||||
|
|
||||||
|
_format = new StringFormat(StringFormatFlags.LineLimit | StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox | StringFormatFlags.MeasureTrailingSpaces);
|
||||||
|
_baseFormatFlags = TextFormatFlags.PreserveGraphicsClipping |
|
||||||
|
TextFormatFlags.PreserveGraphicsTranslateTransform;
|
||||||
|
SetFormatFlags();
|
||||||
|
LeftMargin = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetFormatFlags()
|
||||||
|
{
|
||||||
|
_format.Alignment = TextHelper.TranslateAligment(TextAlign);
|
||||||
|
_format.Trimming = Trimming;
|
||||||
|
|
||||||
|
_formatFlags = _baseFormatFlags | TextHelper.TranslateAligmentToFlag(TextAlign)
|
||||||
|
| TextHelper.TranslateTrimmingToFlag(Trimming);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
return GetLabelSize(node, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Size GetLabelSize(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
return GetLabelSize(node, context, GetLabel(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Size GetLabelSize(TreeNodeAdv node, DrawContext context, string label)
|
||||||
|
{
|
||||||
|
PerformanceAnalyzer.Start("GetLabelSize");
|
||||||
|
CheckThread();
|
||||||
|
Font font = GetDrawingFont(node, context, label);
|
||||||
|
Size s = Size.Empty;
|
||||||
|
if (UseCompatibleTextRendering)
|
||||||
|
s = TextRenderer.MeasureText(label, font);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SizeF sf = context.Graphics.MeasureString(label, font);
|
||||||
|
s = new Size((int)Math.Ceiling(sf.Width), (int)Math.Ceiling(sf.Height));
|
||||||
|
}
|
||||||
|
PerformanceAnalyzer.Finish("GetLabelSize");
|
||||||
|
|
||||||
|
if (!s.IsEmpty)
|
||||||
|
return s;
|
||||||
|
else
|
||||||
|
return new Size(10, Font.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Font GetDrawingFont(TreeNodeAdv node, DrawContext context, string label)
|
||||||
|
{
|
||||||
|
Font font = context.Font;
|
||||||
|
if (DrawTextMustBeFired(node))
|
||||||
|
{
|
||||||
|
DrawEventArgs args = new DrawEventArgs(node, this, context, label);
|
||||||
|
args.Font = context.Font;
|
||||||
|
OnDrawText(args);
|
||||||
|
font = args.Font;
|
||||||
|
}
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetEditControlProperties(Control control, TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
string label = GetLabel(node);
|
||||||
|
DrawContext context = new DrawContext();
|
||||||
|
context.Font = control.Font;
|
||||||
|
control.Font = GetDrawingFont(node, context, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
if (context.CurrentEditorOwner == this && node == Parent.CurrentNode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PerformanceAnalyzer.Start("BaseTextControl.Draw");
|
||||||
|
string label = GetLabel(node);
|
||||||
|
Rectangle bounds = GetBounds(node, context);
|
||||||
|
Rectangle focusRect = new Rectangle(bounds.X, context.Bounds.Y,
|
||||||
|
bounds.Width, context.Bounds.Height);
|
||||||
|
|
||||||
|
Brush backgroundBrush;
|
||||||
|
Color textColor;
|
||||||
|
Font font;
|
||||||
|
CreateBrushes(node, context, label, out backgroundBrush, out textColor, out font, ref label);
|
||||||
|
|
||||||
|
if (backgroundBrush != null)
|
||||||
|
context.Graphics.FillRectangle(backgroundBrush, focusRect);
|
||||||
|
if (context.DrawFocus)
|
||||||
|
{
|
||||||
|
focusRect.Width--;
|
||||||
|
focusRect.Height--;
|
||||||
|
if (context.DrawSelection == DrawSelectionMode.None)
|
||||||
|
_focusPen.Color = SystemColors.ControlText;
|
||||||
|
else
|
||||||
|
_focusPen.Color = SystemColors.InactiveCaption;
|
||||||
|
context.Graphics.DrawRectangle(_focusPen, focusRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
PerformanceAnalyzer.Start("BaseTextControl.DrawText");
|
||||||
|
if (UseCompatibleTextRendering)
|
||||||
|
TextRenderer.DrawText(context.Graphics, label, font, bounds, textColor, _formatFlags);
|
||||||
|
else
|
||||||
|
context.Graphics.DrawString(label, font, GetFrush(textColor), bounds, _format);
|
||||||
|
PerformanceAnalyzer.Finish("BaseTextControl.DrawText");
|
||||||
|
|
||||||
|
PerformanceAnalyzer.Finish("BaseTextControl.Draw");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<Color, Brush> _brushes = new Dictionary<Color,Brush>();
|
||||||
|
private static Brush GetFrush(Color color)
|
||||||
|
{
|
||||||
|
Brush br;
|
||||||
|
if (_brushes.ContainsKey(color))
|
||||||
|
br = _brushes[color];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
br = new SolidBrush(color);
|
||||||
|
_brushes.Add(color, br);
|
||||||
|
}
|
||||||
|
return br;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateBrushes(TreeNodeAdv node, DrawContext context, string text, out Brush backgroundBrush, out Color textColor, out Font font, ref string label)
|
||||||
|
{
|
||||||
|
textColor = Parent.ForeColor;
|
||||||
|
backgroundBrush = null;
|
||||||
|
font = context.Font;
|
||||||
|
if (context.DrawSelection == DrawSelectionMode.Active)
|
||||||
|
{
|
||||||
|
textColor = SystemColors.HighlightText;
|
||||||
|
backgroundBrush = SystemBrushes.Highlight;
|
||||||
|
}
|
||||||
|
else if (context.DrawSelection == DrawSelectionMode.Inactive)
|
||||||
|
{
|
||||||
|
textColor = Parent.ForeColor;
|
||||||
|
backgroundBrush = SystemBrushes.InactiveBorder;
|
||||||
|
}
|
||||||
|
else if (context.DrawSelection == DrawSelectionMode.FullRowSelect)
|
||||||
|
textColor = Parent.ForeColor;
|
||||||
|
|
||||||
|
if (!context.Enabled)
|
||||||
|
textColor = SystemColors.GrayText;
|
||||||
|
|
||||||
|
if (DrawTextMustBeFired(node))
|
||||||
|
{
|
||||||
|
DrawEventArgs args = new DrawEventArgs(node, this, context, text);
|
||||||
|
args.Text = label;
|
||||||
|
args.TextColor = textColor;
|
||||||
|
args.BackgroundBrush = backgroundBrush;
|
||||||
|
args.Font = font;
|
||||||
|
|
||||||
|
OnDrawText(args);
|
||||||
|
|
||||||
|
textColor = args.TextColor;
|
||||||
|
backgroundBrush = args.BackgroundBrush;
|
||||||
|
font = args.Font;
|
||||||
|
label = args.Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetLabel(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
if (node != null && node.Tag != null)
|
||||||
|
{
|
||||||
|
object obj = GetValue(node);
|
||||||
|
if (obj != null)
|
||||||
|
return FormatLabel(obj);
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual string FormatLabel(object obj)
|
||||||
|
{
|
||||||
|
var res = obj.ToString();
|
||||||
|
if (TrimMultiLine && res != null)
|
||||||
|
{
|
||||||
|
string[] parts = res.Split('\n');
|
||||||
|
if (parts.Length > 1)
|
||||||
|
return parts[0] + "...";
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLabel(TreeNodeAdv node, string value)
|
||||||
|
{
|
||||||
|
SetValue(node, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_focusPen.Dispose();
|
||||||
|
_format.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fires when control is going to draw a text. Can be used to change text or back color
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<DrawEventArgs> DrawText;
|
||||||
|
protected virtual void OnDrawText(DrawEventArgs args)
|
||||||
|
{
|
||||||
|
TreeViewAdv tree = args.Node.Tree;
|
||||||
|
if (tree != null)
|
||||||
|
tree.FireDrawControl(args);
|
||||||
|
if (DrawText != null)
|
||||||
|
DrawText(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool DrawTextMustBeFired(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
return DrawText != null || (node.Tree != null && node.Tree.DrawControlMustBeFired());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public abstract class BindableControl : NodeControl
|
||||||
|
{
|
||||||
|
private struct MemberAdapter
|
||||||
|
{
|
||||||
|
private object _obj;
|
||||||
|
private PropertyInfo _pi;
|
||||||
|
private FieldInfo _fi;
|
||||||
|
|
||||||
|
public static readonly MemberAdapter Empty = new MemberAdapter();
|
||||||
|
|
||||||
|
public Type MemberType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_pi != null)
|
||||||
|
return _pi.PropertyType;
|
||||||
|
else if (_fi != null)
|
||||||
|
return _fi.FieldType;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_pi != null && _pi.CanRead)
|
||||||
|
return _pi.GetValue(_obj, null);
|
||||||
|
else if (_fi != null)
|
||||||
|
return _fi.GetValue(_obj);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_pi != null && _pi.CanWrite)
|
||||||
|
_pi.SetValue(_obj, value, null);
|
||||||
|
else if (_fi != null)
|
||||||
|
_fi.SetValue(_obj, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemberAdapter(object obj, PropertyInfo pi)
|
||||||
|
{
|
||||||
|
_obj = obj;
|
||||||
|
_pi = pi;
|
||||||
|
_fi = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemberAdapter(object obj, FieldInfo fi)
|
||||||
|
{
|
||||||
|
_obj = obj;
|
||||||
|
_fi = fi;
|
||||||
|
_pi = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private bool _virtualMode = false;
|
||||||
|
[DefaultValue(false), Category("Data")]
|
||||||
|
public bool VirtualMode
|
||||||
|
{
|
||||||
|
get { return _virtualMode; }
|
||||||
|
set { _virtualMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _propertyName = "";
|
||||||
|
[DefaultValue(""), Category("Data")]
|
||||||
|
public string DataPropertyName
|
||||||
|
{
|
||||||
|
get { return _propertyName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_propertyName == null)
|
||||||
|
_propertyName = string.Empty;
|
||||||
|
_propertyName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _incrementalSearchEnabled = false;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool IncrementalSearchEnabled
|
||||||
|
{
|
||||||
|
get { return _incrementalSearchEnabled; }
|
||||||
|
set { _incrementalSearchEnabled = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public virtual object GetValue(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
if (VirtualMode)
|
||||||
|
{
|
||||||
|
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
|
||||||
|
OnValueNeeded(args);
|
||||||
|
return args.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return GetMemberAdapter(node).Value;
|
||||||
|
}
|
||||||
|
catch (TargetInvocationException ex)
|
||||||
|
{
|
||||||
|
if (ex.InnerException != null)
|
||||||
|
throw new ArgumentException(ex.InnerException.Message, ex.InnerException);
|
||||||
|
else
|
||||||
|
throw new ArgumentException(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void SetValue(TreeNodeAdv node, object value)
|
||||||
|
{
|
||||||
|
if (VirtualMode)
|
||||||
|
{
|
||||||
|
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
|
||||||
|
args.Value = value;
|
||||||
|
OnValuePushed(args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MemberAdapter ma = GetMemberAdapter(node);
|
||||||
|
ma.Value = value;
|
||||||
|
}
|
||||||
|
catch (TargetInvocationException ex)
|
||||||
|
{
|
||||||
|
if (ex.InnerException != null)
|
||||||
|
throw new ArgumentException(ex.InnerException.Message, ex.InnerException);
|
||||||
|
else
|
||||||
|
throw new ArgumentException(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type GetPropertyType(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
return GetMemberAdapter(node).MemberType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MemberAdapter GetMemberAdapter(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
if (node.Tag != null && !string.IsNullOrEmpty(DataPropertyName))
|
||||||
|
{
|
||||||
|
Type type = node.Tag.GetType();
|
||||||
|
PropertyInfo pi = type.GetProperty(DataPropertyName);
|
||||||
|
if (pi != null)
|
||||||
|
return new MemberAdapter(node.Tag, pi);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FieldInfo fi = type.GetField(DataPropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||||
|
if (fi != null)
|
||||||
|
return new MemberAdapter(node.Tag, fi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MemberAdapter.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(DataPropertyName))
|
||||||
|
return GetType().Name;
|
||||||
|
else
|
||||||
|
return string.Format("{0} ({1})", GetType().Name, DataPropertyName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<NodeControlValueEventArgs> ValueNeeded;
|
||||||
|
private void OnValueNeeded(NodeControlValueEventArgs args)
|
||||||
|
{
|
||||||
|
if (ValueNeeded != null)
|
||||||
|
ValueNeeded(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<NodeControlValueEventArgs> ValuePushed;
|
||||||
|
private void OnValuePushed(NodeControlValueEventArgs args)
|
||||||
|
{
|
||||||
|
if (ValuePushed != null)
|
||||||
|
ValuePushed(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||||
|
<Font Name="Microsoft Sans Serif" Size="8.25" />
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeStateIcon" Collapsed="true">
|
||||||
|
<Position X="0.5" Y="4" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeStateIcon.cs</FileName>
|
||||||
|
<HashCode>ABAAAAAAAAQAQAAAAAAAAAAAAAAAAAAAQIAAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.BindableControl" Collapsed="true">
|
||||||
|
<Position X="2.75" Y="1.5" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\BindableControl.cs</FileName>
|
||||||
|
<HashCode>FAAAAAAQIBAQCgAEAAAAIAAAAAAAAAEMAAACAAAAAAE=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeCheckBox" Collapsed="true">
|
||||||
|
<Position X="5" Y="4" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeCheckBox.cs</FileName>
|
||||||
|
<HashCode>AAEAAAAAAAACgkQCAAAAAAigAgAAEGABAAAIAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeControl" Collapsed="true">
|
||||||
|
<Position X="1.5" Y="0.5" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeControl.cs</FileName>
|
||||||
|
<HashCode>AAAAAJAAgIgBkkoQAAgAQAAwAAABEIQAAEBIAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
<Compartments>
|
||||||
|
<Compartment Name="Fields" Collapsed="true" />
|
||||||
|
</Compartments>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeIcon" Collapsed="true">
|
||||||
|
<Position X="0.5" Y="2.75" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeIcon.cs</FileName>
|
||||||
|
<HashCode>ABAAAAAAAAAAAgAAAAAAAAAgAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodePlusMinus" Collapsed="true">
|
||||||
|
<Position X="0.5" Y="1.5" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodePlusMinus.cs</FileName>
|
||||||
|
<HashCode>AAAAAAAAAAAAAgAAAAAAAEAgAAAAMCAAAAAIACAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.BaseTextControl" Collapsed="true">
|
||||||
|
<Position X="3" Y="5" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\BaseTextControl.cs</FileName>
|
||||||
|
<HashCode>AAAAICBQACAAIgACBCAEAQA8AgmFoAAwAAAAACACAMA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeTextBox" Collapsed="true">
|
||||||
|
<Position X="1" Y="6" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeTextBox.cs</FileName>
|
||||||
|
<HashCode>QQQAhAAAADAMgAAAABAAAAAAAgEAIAAAAAAAAIAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.EditableControl" Collapsed="true">
|
||||||
|
<Position X="3" Y="4" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\EditableControl.cs</FileName>
|
||||||
|
<HashCode>QQAgAAAACGgkAMAABAEEkADAEAAUEAAABAGoAAAAAQA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeComboBox" Collapsed="true">
|
||||||
|
<Position X="3" Y="6" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeComboBox.cs</FileName>
|
||||||
|
<HashCode>wQACAAAAAAAMAEBAAAAAAABAAAAAAAABAAAAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeNumericUpDown" Collapsed="true">
|
||||||
|
<Position X="5" Y="6" Width="1.75" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeNumericUpDown.cs</FileName>
|
||||||
|
<HashCode>wQAAAACAAAAEAABAIAAQIAAAAAAAAAABAAAIAAAAAII=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.InteractiveControl" Collapsed="true">
|
||||||
|
<Position X="4" Y="2.75" Width="1.5" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\InteractiveControl.cs</FileName>
|
||||||
|
<HashCode>AAAABAAAAAAAAAAACAAAAAAAABAAAQAAAAAAAAIAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeDecimalTextBox" Collapsed="true">
|
||||||
|
<Position X="2.5" Y="7" Width="1.75" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeDecimalTextBox.cs</FileName>
|
||||||
|
<HashCode>AQAAAAAAAACAAAACAAAAAAQAAAAAIAAAAAgAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
<Class Name="Aga.Controls.Tree.NodeControls.NodeIntegerTextBox" Collapsed="true">
|
||||||
|
<Position X="0.5" Y="7" Width="1.75" />
|
||||||
|
<TypeIdentifier>
|
||||||
|
<FileName>Tree\NodeControls\NodeIntegerTextBox.cs</FileName>
|
||||||
|
<HashCode>AQAAAAAAAAAAAAACAAAAAAQAAAAAIAAAAAAAAAAAAAA=</HashCode>
|
||||||
|
</TypeIdentifier>
|
||||||
|
</Class>
|
||||||
|
</ClassDiagram>
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class DrawEventArgs : NodeEventArgs
|
||||||
|
{
|
||||||
|
private DrawContext _context;
|
||||||
|
public DrawContext Context
|
||||||
|
{
|
||||||
|
get { return _context; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Brush _textBrush;
|
||||||
|
[Obsolete("Use TextColor")]
|
||||||
|
public Brush TextBrush
|
||||||
|
{
|
||||||
|
get { return _textBrush; }
|
||||||
|
set { _textBrush = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Brush _backgroundBrush;
|
||||||
|
public Brush BackgroundBrush
|
||||||
|
{
|
||||||
|
get { return _backgroundBrush; }
|
||||||
|
set { _backgroundBrush = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Font _font;
|
||||||
|
public Font Font
|
||||||
|
{
|
||||||
|
get { return _font; }
|
||||||
|
set { _font = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _textColor;
|
||||||
|
public Color TextColor
|
||||||
|
{
|
||||||
|
get { return _textColor; }
|
||||||
|
set { _textColor = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _text;
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get { return _text; }
|
||||||
|
set { _text = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private EditableControl _control;
|
||||||
|
public EditableControl Control
|
||||||
|
{
|
||||||
|
get { return _control; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DrawEventArgs(TreeNodeAdv node, EditableControl control, DrawContext context, string text)
|
||||||
|
: base(node)
|
||||||
|
{
|
||||||
|
_control = control;
|
||||||
|
_context = context;
|
||||||
|
_text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class EditEventArgs : NodeEventArgs
|
||||||
|
{
|
||||||
|
private Control _control;
|
||||||
|
public Control Control
|
||||||
|
{
|
||||||
|
get { return _control; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditEventArgs(TreeNodeAdv node, Control control)
|
||||||
|
: base(node)
|
||||||
|
{
|
||||||
|
_control = control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public abstract class EditableControl : InteractiveControl
|
||||||
|
{
|
||||||
|
private Timer _timer;
|
||||||
|
private bool _editFlag;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private bool _editOnClick = false;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool EditOnClick
|
||||||
|
{
|
||||||
|
get { return _editOnClick; }
|
||||||
|
set { _editOnClick = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
protected EditableControl()
|
||||||
|
{
|
||||||
|
_timer = new Timer();
|
||||||
|
_timer.Interval = 500;
|
||||||
|
_timer.Tick += new EventHandler(TimerTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TimerTick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_timer.Stop();
|
||||||
|
if (_editFlag)
|
||||||
|
BeginEdit();
|
||||||
|
_editFlag = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetEditorBounds(EditorContext context)
|
||||||
|
{
|
||||||
|
Size size = CalculateEditorSize(context);
|
||||||
|
context.Editor.Bounds = new Rectangle(context.Bounds.X, context.Bounds.Y,
|
||||||
|
Math.Min(size.Width, context.Bounds.Width),
|
||||||
|
Math.Min(size.Height, Parent.ClientSize.Height - context.Bounds.Y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Size CalculateEditorSize(EditorContext context);
|
||||||
|
|
||||||
|
protected virtual bool CanEdit(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
return (node.Tag != null) && IsEditEnabled(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BeginEdit()
|
||||||
|
{
|
||||||
|
if (Parent != null && Parent.CurrentNode != null && CanEdit(Parent.CurrentNode))
|
||||||
|
{
|
||||||
|
CancelEventArgs args = new CancelEventArgs();
|
||||||
|
OnEditorShowing(args);
|
||||||
|
if (!args.Cancel)
|
||||||
|
{
|
||||||
|
var editor = CreateEditor(Parent.CurrentNode);
|
||||||
|
Parent.DisplayEditor(editor, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EndEdit(bool applyChanges)
|
||||||
|
{
|
||||||
|
if (Parent != null)
|
||||||
|
if (Parent.HideEditor(applyChanges))
|
||||||
|
OnEditorHided();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void UpdateEditor(Control control)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ApplyChanges(TreeNodeAdv node, Control editor)
|
||||||
|
{
|
||||||
|
DoApplyChanges(node, editor);
|
||||||
|
OnChangesApplied();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void DoDisposeEditor(Control editor)
|
||||||
|
{
|
||||||
|
DisposeEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void DoApplyChanges(TreeNodeAdv node, Control editor);
|
||||||
|
|
||||||
|
protected abstract Control CreateEditor(TreeNodeAdv node);
|
||||||
|
|
||||||
|
protected abstract void DisposeEditor(Control editor);
|
||||||
|
|
||||||
|
public virtual void Cut(Control control)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Copy(Control control)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Paste(Control control)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Delete(Control control)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
_editFlag = (!EditOnClick && args.Button == MouseButtons.Left
|
||||||
|
&& args.ModifierKeys == Keys.None && args.Node.IsSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Node.IsSelected)
|
||||||
|
{
|
||||||
|
if (EditOnClick && args.Button == MouseButtons.Left && args.ModifierKeys == Keys.None)
|
||||||
|
{
|
||||||
|
Parent.ItemDragMode = false;
|
||||||
|
BeginEdit();
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
else if (_editFlag)// && args.Node.IsSelected)
|
||||||
|
_timer.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
_editFlag = false;
|
||||||
|
_timer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (disposing)
|
||||||
|
_timer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
public event CancelEventHandler EditorShowing;
|
||||||
|
protected void OnEditorShowing(CancelEventArgs args)
|
||||||
|
{
|
||||||
|
if (EditorShowing != null)
|
||||||
|
EditorShowing(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler EditorHided;
|
||||||
|
protected void OnEditorHided()
|
||||||
|
{
|
||||||
|
if (EditorHided != null)
|
||||||
|
EditorHided(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler ChangesApplied;
|
||||||
|
protected void OnChangesApplied()
|
||||||
|
{
|
||||||
|
if (ChangesApplied != null)
|
||||||
|
ChangesApplied(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Displays an animated icon for those nodes, who are in expanding state.
|
||||||
|
/// Parent TreeView must have AsyncExpanding property set to true.
|
||||||
|
/// </summary>
|
||||||
|
public class ExpandingIcon: NodeControl
|
||||||
|
{
|
||||||
|
private static GifDecoder _gif = ResourceHelper.LoadingIcon;
|
||||||
|
private static int _index = 0;
|
||||||
|
private static volatile Thread _animatingThread;
|
||||||
|
private static object _lock = new object();
|
||||||
|
|
||||||
|
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
return ResourceHelper.LoadingIcon.FrameSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnIsVisibleValueNeeded(NodeControlValueEventArgs args)
|
||||||
|
{
|
||||||
|
args.Value = args.Node.IsExpandingNow;
|
||||||
|
base.OnIsVisibleValueNeeded(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
Rectangle rect = GetBounds(node, context);
|
||||||
|
Image img = _gif.GetFrame(_index).Image;
|
||||||
|
context.Graphics.DrawImage(img, rect.Location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Start()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_animatingThread == null)
|
||||||
|
{
|
||||||
|
_index = 0;
|
||||||
|
_animatingThread = new Thread(new ThreadStart(IterateIcons));
|
||||||
|
_animatingThread.IsBackground = true;
|
||||||
|
_animatingThread.Priority = ThreadPriority.Lowest;
|
||||||
|
_animatingThread.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Stop()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_index = 0;
|
||||||
|
_animatingThread = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IterateIcons()
|
||||||
|
{
|
||||||
|
while (_animatingThread != null)
|
||||||
|
{
|
||||||
|
if (_index < _gif.FrameCount - 1)
|
||||||
|
_index++;
|
||||||
|
else
|
||||||
|
_index = 0;
|
||||||
|
|
||||||
|
if (IconChanged != null)
|
||||||
|
IconChanged(null, EventArgs.Empty);
|
||||||
|
|
||||||
|
int delay = _gif.GetFrame(_index).Delay;
|
||||||
|
Thread.Sleep(delay);
|
||||||
|
}
|
||||||
|
System.Diagnostics.Debug.WriteLine("IterateIcons Stopped");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static event EventHandler IconChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public abstract class InteractiveControl : BindableControl
|
||||||
|
{
|
||||||
|
private bool _editEnabled = false;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool EditEnabled
|
||||||
|
{
|
||||||
|
get { return _editEnabled; }
|
||||||
|
set { _editEnabled = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool IsEditEnabled(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
if (EditEnabled)
|
||||||
|
{
|
||||||
|
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
|
||||||
|
args.Value = true;
|
||||||
|
OnIsEditEnabledValueNeeded(args);
|
||||||
|
return Convert.ToBoolean(args.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<NodeControlValueEventArgs> IsEditEnabledValueNeeded;
|
||||||
|
private void OnIsEditEnabledValueNeeded(NodeControlValueEventArgs args)
|
||||||
|
{
|
||||||
|
if (IsEditEnabledValueNeeded != null)
|
||||||
|
IsEditEnabledValueNeeded(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class LabelEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
private object _subject;
|
||||||
|
public object Subject
|
||||||
|
{
|
||||||
|
get { return _subject; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _oldLabel;
|
||||||
|
public string OldLabel
|
||||||
|
{
|
||||||
|
get { return _oldLabel; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _newLabel;
|
||||||
|
public string NewLabel
|
||||||
|
{
|
||||||
|
get { return _newLabel; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public LabelEventArgs(object subject, string oldLabel, string newLabel)
|
||||||
|
{
|
||||||
|
_subject = subject;
|
||||||
|
_oldLabel = oldLabel;
|
||||||
|
_newLabel = newLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Properties;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Forms.VisualStyles;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeCheckBox : InteractiveControl
|
||||||
|
{
|
||||||
|
public const int ImageSize = 13;
|
||||||
|
|
||||||
|
private Bitmap _check;
|
||||||
|
private Bitmap _uncheck;
|
||||||
|
private Bitmap _unknown;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private bool _threeState;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool ThreeState
|
||||||
|
{
|
||||||
|
get { return _threeState; }
|
||||||
|
set { _threeState = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public NodeCheckBox()
|
||||||
|
: this(string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeCheckBox(string propertyName)
|
||||||
|
{
|
||||||
|
_check = Resources.check;
|
||||||
|
_uncheck = Resources.uncheck;
|
||||||
|
_unknown = Resources.unknown;
|
||||||
|
DataPropertyName = propertyName;
|
||||||
|
LeftMargin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
int scaledX = node.Tree.GetScaledSize(ImageSize, false);
|
||||||
|
int scaledY = node.Tree.GetScaledSize(ImageSize);
|
||||||
|
return new Size(scaledX, scaledY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
Rectangle bounds = GetBounds(node, context);
|
||||||
|
CheckState state = GetCheckState(node);
|
||||||
|
if (TreeViewAdv.CustomCheckRenderFunc != null)
|
||||||
|
{
|
||||||
|
TreeViewAdv.CustomCheckRenderFunc(context.Graphics, bounds, state == CheckState.Checked);
|
||||||
|
}
|
||||||
|
else if (Application.RenderWithVisualStyles)
|
||||||
|
{
|
||||||
|
VisualStyleRenderer renderer;
|
||||||
|
int scaledX = node.Tree.GetScaledSize(ImageSize, false);
|
||||||
|
int scaledY = node.Tree.GetScaledSize(ImageSize);
|
||||||
|
if (state == CheckState.Indeterminate)
|
||||||
|
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.MixedNormal);
|
||||||
|
else if (state == CheckState.Checked)
|
||||||
|
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.CheckedNormal);
|
||||||
|
else
|
||||||
|
renderer = new VisualStyleRenderer(VisualStyleElement.Button.CheckBox.UncheckedNormal);
|
||||||
|
renderer.DrawBackground(context.Graphics, new Rectangle(bounds.X, bounds.Y, scaledX, scaledY));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Image img;
|
||||||
|
if (state == CheckState.Indeterminate)
|
||||||
|
img = _unknown;
|
||||||
|
else if (state == CheckState.Checked)
|
||||||
|
img = _check;
|
||||||
|
else
|
||||||
|
img = _uncheck;
|
||||||
|
context.Graphics.DrawImage(img, bounds.Location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual CheckState GetCheckState(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
object obj = GetValue(node);
|
||||||
|
if (obj is CheckState)
|
||||||
|
return (CheckState)obj;
|
||||||
|
else if (obj is bool)
|
||||||
|
return (bool)obj ? CheckState.Checked : CheckState.Unchecked;
|
||||||
|
else
|
||||||
|
return CheckState.Unchecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void SetCheckState(TreeNodeAdv node, CheckState value)
|
||||||
|
{
|
||||||
|
if (VirtualMode)
|
||||||
|
{
|
||||||
|
SetValue(node, value);
|
||||||
|
OnCheckStateChanged(node);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Type type = GetPropertyType(node);
|
||||||
|
if (type == typeof(CheckState))
|
||||||
|
{
|
||||||
|
SetValue(node, value);
|
||||||
|
OnCheckStateChanged(node);
|
||||||
|
}
|
||||||
|
else if (type == typeof(bool))
|
||||||
|
{
|
||||||
|
SetValue(node, value != CheckState.Unchecked);
|
||||||
|
OnCheckStateChanged(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Button == MouseButtons.Left && IsEditEnabled(args.Node))
|
||||||
|
{
|
||||||
|
DrawContext context = new DrawContext();
|
||||||
|
context.Bounds = args.ControlBounds;
|
||||||
|
Rectangle rect = GetBounds(args.Node, context);
|
||||||
|
if (rect.Contains(args.ViewLocation))
|
||||||
|
{
|
||||||
|
CheckState state = GetCheckState(args.Node);
|
||||||
|
state = GetNewState(state);
|
||||||
|
SetCheckState(args.Node, state);
|
||||||
|
Parent.UpdateView();
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckState GetNewState(CheckState state)
|
||||||
|
{
|
||||||
|
if (state == CheckState.Indeterminate)
|
||||||
|
return CheckState.Unchecked;
|
||||||
|
else if(state == CheckState.Unchecked)
|
||||||
|
return CheckState.Checked;
|
||||||
|
else
|
||||||
|
return ThreeState ? CheckState.Indeterminate : CheckState.Unchecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.KeyCode == Keys.Space && EditEnabled)
|
||||||
|
{
|
||||||
|
Parent.BeginUpdate();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Parent.CurrentNode != null)
|
||||||
|
{
|
||||||
|
CheckState value = GetNewState(GetCheckState(Parent.CurrentNode));
|
||||||
|
foreach (TreeNodeAdv node in Parent.Selection)
|
||||||
|
if (IsEditEnabled(node))
|
||||||
|
SetCheckState(node, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Parent.EndUpdate();
|
||||||
|
}
|
||||||
|
args.Handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreePathEventArgs> CheckStateChanged;
|
||||||
|
protected void OnCheckStateChanged(TreePathEventArgs args)
|
||||||
|
{
|
||||||
|
if (CheckStateChanged != null)
|
||||||
|
CheckStateChanged(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnCheckStateChanged(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
TreePath path = this.Parent.GetPath(node);
|
||||||
|
OnCheckStateChanged(new TreePathEventArgs(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing.Design;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeComboBox : BaseTextControl
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private int _editorWidth = 100;
|
||||||
|
[DefaultValue(100)]
|
||||||
|
public int EditorWidth
|
||||||
|
{
|
||||||
|
get { return _editorWidth; }
|
||||||
|
set { _editorWidth = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _editorHeight = 100;
|
||||||
|
[DefaultValue(100)]
|
||||||
|
public int EditorHeight
|
||||||
|
{
|
||||||
|
get { return _editorHeight; }
|
||||||
|
set { _editorHeight = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<object> _dropDownItems;
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
|
||||||
|
[Editor(typeof(StringCollectionEditor), typeof(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||||
|
public List<object> DropDownItems
|
||||||
|
{
|
||||||
|
get { return _dropDownItems; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public event EventHandler<EditEventArgs> CreatingEditor;
|
||||||
|
|
||||||
|
public NodeComboBox()
|
||||||
|
{
|
||||||
|
_dropDownItems = new List<object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Size CalculateEditorSize(EditorContext context)
|
||||||
|
{
|
||||||
|
if (Parent.UseColumns)
|
||||||
|
{
|
||||||
|
if (context.Editor is CheckedListBox)
|
||||||
|
return new Size(context.Bounds.Size.Width, EditorHeight);
|
||||||
|
else
|
||||||
|
return context.Bounds.Size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (context.Editor is CheckedListBox)
|
||||||
|
return new Size(EditorWidth, EditorHeight);
|
||||||
|
else
|
||||||
|
return new Size(EditorWidth, context.Bounds.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Control CreateEditor(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
Control c;
|
||||||
|
object value = GetValue(node);
|
||||||
|
if (IsCheckedListBoxRequired(node))
|
||||||
|
c = CreateCheckedListBox(node);
|
||||||
|
else
|
||||||
|
c = CreateCombo(node);
|
||||||
|
OnCreatingEditor(new EditEventArgs(node, c));
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DisposeEditor(Control editor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnCreatingEditor(EditEventArgs args)
|
||||||
|
{
|
||||||
|
if (CreatingEditor != null)
|
||||||
|
CreatingEditor(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool IsCheckedListBoxRequired(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
object value = GetValue(node);
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
Type t = value.GetType();
|
||||||
|
object[] arr = t.GetCustomAttributes(typeof(FlagsAttribute), false);
|
||||||
|
return (t.IsEnum && arr.Length == 1);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Control CreateCombo(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
ComboBox comboBox = new ComboBox();
|
||||||
|
if (DropDownItems != null)
|
||||||
|
comboBox.Items.AddRange(DropDownItems.ToArray());
|
||||||
|
comboBox.SelectedItem = GetValue(node);
|
||||||
|
comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||||
|
comboBox.DropDownClosed += new EventHandler(EditorDropDownClosed);
|
||||||
|
SetEditControlProperties(comboBox, node);
|
||||||
|
return comboBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Control CreateCheckedListBox(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
CheckedListBox listBox = new CheckedListBox();
|
||||||
|
listBox.CheckOnClick = true;
|
||||||
|
|
||||||
|
object value = GetValue(node);
|
||||||
|
Type enumType = GetEnumType(node);
|
||||||
|
foreach (object obj in Enum.GetValues(enumType))
|
||||||
|
{
|
||||||
|
object[] attributes = enumType.GetField(obj.ToString()).GetCustomAttributes(typeof(BrowsableAttribute), false);
|
||||||
|
if (attributes.Length == 0 || ((BrowsableAttribute)attributes[0]).Browsable)
|
||||||
|
listBox.Items.Add(obj, IsContain(value, obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
SetEditControlProperties(listBox, node);
|
||||||
|
if (CreatingEditor != null)
|
||||||
|
CreatingEditor(this, new EditEventArgs(node, listBox));
|
||||||
|
return listBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Type GetEnumType(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
object value = GetValue(node);
|
||||||
|
return value.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsContain(object value, object enumElement)
|
||||||
|
{
|
||||||
|
if (value == null || enumElement == null)
|
||||||
|
return false;
|
||||||
|
if (value.GetType().IsEnum)
|
||||||
|
{
|
||||||
|
int i1 = (int)value;
|
||||||
|
int i2 = (int)enumElement;
|
||||||
|
return (i1 & i2) == i2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var arr = value as object[];
|
||||||
|
foreach (object obj in arr)
|
||||||
|
if ((int)obj == (int)enumElement)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override string FormatLabel(object obj)
|
||||||
|
{
|
||||||
|
var arr = obj as object[];
|
||||||
|
if (arr != null)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (object t in arr)
|
||||||
|
{
|
||||||
|
if (sb.Length > 0)
|
||||||
|
sb.Append(", ");
|
||||||
|
sb.Append(t);
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return base.FormatLabel(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDropDownClosed(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
EndEdit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdateEditor(Control control)
|
||||||
|
{
|
||||||
|
if (control is ComboBox)
|
||||||
|
(control as ComboBox).DroppedDown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
|
||||||
|
{
|
||||||
|
var combo = editor as ComboBox;
|
||||||
|
if (combo != null)
|
||||||
|
{
|
||||||
|
if (combo.DropDownStyle == ComboBoxStyle.DropDown)
|
||||||
|
SetValue(node, combo.Text);
|
||||||
|
else
|
||||||
|
SetValue(node, combo.SelectedItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var listBox = editor as CheckedListBox;
|
||||||
|
Type type = GetEnumType(node);
|
||||||
|
if (IsFlags(type))
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
foreach (object obj in listBox.CheckedItems)
|
||||||
|
res |= (int)obj;
|
||||||
|
object val = Enum.ToObject(type, res);
|
||||||
|
SetValue(node, val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<object> list = new List<object>();
|
||||||
|
foreach (object obj in listBox.CheckedItems)
|
||||||
|
list.Add(obj);
|
||||||
|
SetValue(node, list.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsFlags(Type type)
|
||||||
|
{
|
||||||
|
object[] atr = type.GetCustomAttributes(typeof(FlagsAttribute), false);
|
||||||
|
return atr.Length == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseUp(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Node != null && args.Node.IsSelected) //Workaround of specific ComboBox control behavior
|
||||||
|
base.MouseUp(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
[DesignTimeVisible(false), ToolboxItem(false)]
|
||||||
|
public abstract class NodeControl : Component
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private TreeViewAdv _parent;
|
||||||
|
[Browsable(false)]
|
||||||
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||||
|
public TreeViewAdv Parent
|
||||||
|
{
|
||||||
|
get { return _parent; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _parent)
|
||||||
|
{
|
||||||
|
if (_parent != null)
|
||||||
|
_parent.NodeControls.Remove(this);
|
||||||
|
|
||||||
|
if (value != null)
|
||||||
|
value.NodeControls.Add(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IToolTipProvider _toolTipProvider;
|
||||||
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||||
|
public IToolTipProvider ToolTipProvider
|
||||||
|
{
|
||||||
|
get { return _toolTipProvider; }
|
||||||
|
set { _toolTipProvider = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeColumn _parentColumn;
|
||||||
|
public TreeColumn ParentColumn
|
||||||
|
{
|
||||||
|
get { return _parentColumn; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_parentColumn = value;
|
||||||
|
if (_parent != null)
|
||||||
|
_parent.FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private VerticalAlignment _verticalAlign = VerticalAlignment.Center;
|
||||||
|
[DefaultValue(VerticalAlignment.Center)]
|
||||||
|
public VerticalAlignment VerticalAlign
|
||||||
|
{
|
||||||
|
get { return _verticalAlign; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_verticalAlign = value;
|
||||||
|
if (_parent != null)
|
||||||
|
_parent.FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _leftMargin = 0;
|
||||||
|
public int LeftMargin
|
||||||
|
{
|
||||||
|
get { return _leftMargin; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
|
||||||
|
_leftMargin = value;
|
||||||
|
if (_parent != null)
|
||||||
|
_parent.FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
internal virtual void AssignParent(TreeViewAdv parent)
|
||||||
|
{
|
||||||
|
_parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Rectangle GetBounds(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
Rectangle r = context.Bounds;
|
||||||
|
Size s = GetActualSize(node, context);
|
||||||
|
Size bs = new Size(r.Width - LeftMargin, Math.Min(r.Height, s.Height));
|
||||||
|
switch (VerticalAlign)
|
||||||
|
{
|
||||||
|
case VerticalAlignment.Top:
|
||||||
|
return new Rectangle(new Point(r.X + LeftMargin, r.Y), bs);
|
||||||
|
case VerticalAlignment.Bottom:
|
||||||
|
return new Rectangle(new Point(r.X + LeftMargin, r.Bottom - s.Height), bs);
|
||||||
|
default:
|
||||||
|
return new Rectangle(new Point(r.X + LeftMargin, r.Y + (r.Height - s.Height) / 2), bs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void CheckThread()
|
||||||
|
{
|
||||||
|
if (Parent != null && Control.CheckForIllegalCrossThreadCalls)
|
||||||
|
if (Parent.InvokeRequired)
|
||||||
|
throw new InvalidOperationException("Cross-thread calls are not allowed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsVisible(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
NodeControlValueEventArgs args = new NodeControlValueEventArgs(node);
|
||||||
|
args.Value = true;
|
||||||
|
OnIsVisibleValueNeeded(args);
|
||||||
|
return Convert.ToBoolean(args.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Size GetActualSize(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
if (IsVisible(node))
|
||||||
|
{
|
||||||
|
Size s = MeasureSize(node, context);
|
||||||
|
return new Size(s.Width + LeftMargin, s.Height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Size.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Size MeasureSize(TreeNodeAdv node, DrawContext context);
|
||||||
|
|
||||||
|
public abstract void Draw(TreeNodeAdv node, DrawContext context);
|
||||||
|
|
||||||
|
public virtual string GetToolTip(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
if (ToolTipProvider != null)
|
||||||
|
return ToolTipProvider.GetToolTip(node, this);
|
||||||
|
else
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void MouseUp(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void KeyDown(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void KeyUp(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<NodeControlValueEventArgs> IsVisibleValueNeeded;
|
||||||
|
protected virtual void OnIsVisibleValueNeeded(NodeControlValueEventArgs args)
|
||||||
|
{
|
||||||
|
if (IsVisibleValueNeeded != null)
|
||||||
|
IsVisibleValueNeeded(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeControlValueEventArgs : NodeEventArgs
|
||||||
|
{
|
||||||
|
private object _value;
|
||||||
|
public object Value
|
||||||
|
{
|
||||||
|
get { return _value; }
|
||||||
|
set { _value = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeControlValueEventArgs(TreeNodeAdv node)
|
||||||
|
:base(node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.ComponentModel.Design;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing.Design;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
internal class NodeControlsCollection : Collection<NodeControl>
|
||||||
|
{
|
||||||
|
private TreeViewAdv _tree;
|
||||||
|
|
||||||
|
public NodeControlsCollection(TreeViewAdv tree)
|
||||||
|
{
|
||||||
|
_tree = tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ClearItems()
|
||||||
|
{
|
||||||
|
_tree.BeginUpdate();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (this.Count != 0)
|
||||||
|
this.RemoveAt(this.Count - 1);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_tree.EndUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InsertItem(int index, NodeControl item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
|
||||||
|
if (item.Parent != _tree)
|
||||||
|
{
|
||||||
|
if (item.Parent != null)
|
||||||
|
{
|
||||||
|
item.Parent.NodeControls.Remove(item);
|
||||||
|
}
|
||||||
|
base.InsertItem(index, item);
|
||||||
|
item.AssignParent(_tree);
|
||||||
|
_tree.FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RemoveItem(int index)
|
||||||
|
{
|
||||||
|
NodeControl value = this[index];
|
||||||
|
value.AssignParent(null);
|
||||||
|
base.RemoveItem(index);
|
||||||
|
_tree.FullUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetItem(int index, NodeControl item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
|
||||||
|
_tree.BeginUpdate();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RemoveAt(index);
|
||||||
|
InsertItem(index, item);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_tree.EndUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NodeControlCollectionEditor : CollectionEditor
|
||||||
|
{
|
||||||
|
private Type[] _types;
|
||||||
|
|
||||||
|
public NodeControlCollectionEditor(Type type)
|
||||||
|
: base(type)
|
||||||
|
{
|
||||||
|
_types = new Type[] { typeof(NodeTextBox), typeof(NodeIntegerTextBox), typeof(NodeDecimalTextBox),
|
||||||
|
typeof(NodeComboBox), typeof(NodeCheckBox),
|
||||||
|
typeof(NodeStateIcon), typeof(NodeIcon), typeof(NodeNumericUpDown), typeof(ExpandingIcon) };
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override System.Type[] CreateNewItemTypes()
|
||||||
|
{
|
||||||
|
return _types;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeDecimalTextBox : NodeTextBox
|
||||||
|
{
|
||||||
|
private bool _allowDecimalSeparator = true;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool AllowDecimalSeparator
|
||||||
|
{
|
||||||
|
get { return _allowDecimalSeparator; }
|
||||||
|
set { _allowDecimalSeparator = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _allowNegativeSign = true;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool AllowNegativeSign
|
||||||
|
{
|
||||||
|
get { return _allowNegativeSign; }
|
||||||
|
set { _allowNegativeSign = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected NodeDecimalTextBox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TextBox CreateTextBox()
|
||||||
|
{
|
||||||
|
NumericTextBox textBox = new NumericTextBox();
|
||||||
|
textBox.AllowDecimalSeparator = AllowDecimalSeparator;
|
||||||
|
textBox.AllowNegativeSign = AllowNegativeSign;
|
||||||
|
return textBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
|
||||||
|
{
|
||||||
|
SetValue(node, (editor as NumericTextBox).DecimalValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
private TreeNodeAdv _node;
|
||||||
|
public TreeNodeAdv Node
|
||||||
|
{
|
||||||
|
get { return _node; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeEventArgs(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
_node = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Aga.Controls.Properties;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeIcon : BindableControl
|
||||||
|
{
|
||||||
|
public NodeIcon()
|
||||||
|
{
|
||||||
|
LeftMargin = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
Image image = GetIcon(node);
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
int scaledX = node.Tree.GetScaledSize(image.Size.Width, false);
|
||||||
|
int scaledY = node.Tree.GetScaledSize(image.Size.Height);
|
||||||
|
return new Size(scaledX, scaledY); ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Size.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void Draw(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
Image image = GetIcon(node);
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
Rectangle r = GetBounds(node, context);
|
||||||
|
if ( image.Width > 0 && image.Height > 0 )
|
||||||
|
{
|
||||||
|
switch (_scaleMode)
|
||||||
|
{
|
||||||
|
case ImageScaleMode.Fit:
|
||||||
|
context.Graphics.DrawImage(image, r);
|
||||||
|
break;
|
||||||
|
case ImageScaleMode.ScaleDown:
|
||||||
|
{
|
||||||
|
float factor = Math.Min((float)r.Width / (float)image.Width, (float)r.Height / (float)image.Height);
|
||||||
|
if (factor < 1)
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
|
||||||
|
else
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
|
||||||
|
} break;
|
||||||
|
case ImageScaleMode.ScaleUp:
|
||||||
|
{
|
||||||
|
float factor = Math.Max((float)r.Width / (float)image.Width, (float)r.Height / (float)image.Height);
|
||||||
|
if (factor > 1)
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
|
||||||
|
else
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
|
||||||
|
} break;
|
||||||
|
case ImageScaleMode.AlwaysScale:
|
||||||
|
{
|
||||||
|
float fx = (float)r.Width / (float)image.Width;
|
||||||
|
float fy = (float)r.Height / (float)image.Height;
|
||||||
|
if (Math.Min(fx, fy) < 1)
|
||||||
|
{ //scale down
|
||||||
|
float factor = Math.Min(fx, fy);
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
|
||||||
|
}
|
||||||
|
else if (Math.Max(fx, fy) > 1)
|
||||||
|
{
|
||||||
|
float factor = Math.Max(fx, fy);
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width * factor, image.Height * factor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
|
||||||
|
} break;
|
||||||
|
case ImageScaleMode.Clip:
|
||||||
|
default:
|
||||||
|
context.Graphics.DrawImage(image, r.X, r.Y, image.Width, image.Height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual Image GetIcon(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
return GetValue(node) as Image;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageScaleMode _scaleMode = ImageScaleMode.Clip;
|
||||||
|
[DefaultValue("Clip"), Category("Appearance")]
|
||||||
|
public ImageScaleMode ScaleMode
|
||||||
|
{
|
||||||
|
get { return _scaleMode; }
|
||||||
|
set { _scaleMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
|
||||||
|
public class NodeIntegerTextBox : NodeTextBox
|
||||||
|
{
|
||||||
|
private bool _allowNegativeSign = true;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool AllowNegativeSign
|
||||||
|
{
|
||||||
|
get { return _allowNegativeSign; }
|
||||||
|
set { _allowNegativeSign = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodeIntegerTextBox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TextBox CreateTextBox()
|
||||||
|
{
|
||||||
|
NumericTextBox textBox = new NumericTextBox();
|
||||||
|
textBox.AllowDecimalSeparator = false;
|
||||||
|
textBox.AllowNegativeSign = AllowNegativeSign;
|
||||||
|
return textBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
|
||||||
|
{
|
||||||
|
SetValue(node, (editor as NumericTextBox).IntValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing.Design;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeNumericUpDown : BaseTextControl
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private int _editorWidth = 100;
|
||||||
|
[DefaultValue(100)]
|
||||||
|
public int EditorWidth
|
||||||
|
{
|
||||||
|
get { return _editorWidth; }
|
||||||
|
set { _editorWidth = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _decimalPlaces = 0;
|
||||||
|
[Category("Data"), DefaultValue(0)]
|
||||||
|
public int DecimalPlaces
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this._decimalPlaces;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this._decimalPlaces = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal _increment = 1;
|
||||||
|
[Category("Data"), DefaultValue(1)]
|
||||||
|
public decimal Increment
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this._increment;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this._increment = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal _minimum = 0;
|
||||||
|
[Category("Data"), DefaultValue(0)]
|
||||||
|
public decimal Minimum
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _minimum;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_minimum = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private decimal _maximum = 100;
|
||||||
|
[Category("Data"), DefaultValue(100)]
|
||||||
|
public decimal Maximum
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this._maximum;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this._maximum = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public NodeNumericUpDown()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Size CalculateEditorSize(EditorContext context)
|
||||||
|
{
|
||||||
|
if (Parent.UseColumns)
|
||||||
|
return context.Bounds.Size;
|
||||||
|
else
|
||||||
|
return new Size(EditorWidth, context.Bounds.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Control CreateEditor(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
NumericUpDown num = new NumericUpDown();
|
||||||
|
num.Increment = Increment;
|
||||||
|
num.DecimalPlaces = DecimalPlaces;
|
||||||
|
num.Minimum = Minimum;
|
||||||
|
num.Maximum = Maximum;
|
||||||
|
num.Value = (decimal)GetValue(node);
|
||||||
|
SetEditControlProperties(num, node);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DisposeEditor(Control editor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
|
||||||
|
{
|
||||||
|
SetValue(node, (editor as NumericUpDown).Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Properties;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Forms.VisualStyles;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
internal class NodePlusMinus : NodeControl
|
||||||
|
{
|
||||||
|
public const int ImageSize = 9;
|
||||||
|
public const int Width = 16;
|
||||||
|
private Bitmap _plus;
|
||||||
|
private Bitmap _minus;
|
||||||
|
|
||||||
|
private VisualStyleRenderer _openedRenderer;
|
||||||
|
private VisualStyleRenderer OpenedRenderer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_openedRenderer == null)
|
||||||
|
_openedRenderer = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Opened);
|
||||||
|
return _openedRenderer;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private VisualStyleRenderer _closedRenderer;
|
||||||
|
private VisualStyleRenderer ClosedRenderer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_closedRenderer == null)
|
||||||
|
_closedRenderer = new VisualStyleRenderer(VisualStyleElement.TreeView.Glyph.Closed);
|
||||||
|
return _closedRenderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NodePlusMinus()
|
||||||
|
{
|
||||||
|
_plus = Resources.plus;
|
||||||
|
_minus = Resources.minus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Size MeasureSize(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
int scaledX = node.Tree.GetScaledSize(Width, false);
|
||||||
|
int scaledY = node.Tree.GetScaledSize(Width);
|
||||||
|
return new Size(scaledX, scaledY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
if (node.CanExpand)
|
||||||
|
{
|
||||||
|
Rectangle r = context.Bounds;
|
||||||
|
int scaledX = node.Tree.GetScaledSize(ImageSize, false);
|
||||||
|
int scaledY = node.Tree.GetScaledSize(ImageSize);
|
||||||
|
int dy = (int)Math.Round((float)(r.Height - scaledY) / 2);
|
||||||
|
if (TreeViewAdv.CustomPlusMinusRenderFunc != null)
|
||||||
|
{
|
||||||
|
TreeViewAdv.CustomPlusMinusRenderFunc(context.Graphics, r, node.IsExpanded);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (Application.RenderWithVisualStyles)
|
||||||
|
{
|
||||||
|
VisualStyleRenderer renderer;
|
||||||
|
if (node.IsExpanded)
|
||||||
|
renderer = OpenedRenderer;
|
||||||
|
else
|
||||||
|
renderer = ClosedRenderer;
|
||||||
|
renderer.DrawBackground(context.Graphics, new Rectangle(r.X, r.Y + dy, scaledX, scaledY));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Image img;
|
||||||
|
if (node.IsExpanded)
|
||||||
|
img = _minus;
|
||||||
|
else
|
||||||
|
img = _plus;
|
||||||
|
context.Graphics.DrawImageUnscaled(img, new Point(r.X, r.Y + dy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDown(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Button == MouseButtons.Left)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
if (args.Node.CanExpand)
|
||||||
|
args.Node.IsExpanded = !args.Node.IsExpanded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MouseDoubleClick(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
args.Handled = true; // Supress expand/collapse when double click on plus/minus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Properties;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeStateIcon: NodeIcon
|
||||||
|
{
|
||||||
|
private Image _leaf;
|
||||||
|
private Image _opened;
|
||||||
|
private Image _closed;
|
||||||
|
|
||||||
|
public NodeStateIcon()
|
||||||
|
{
|
||||||
|
_leaf = MakeTransparent(Resources.Leaf);
|
||||||
|
_opened = MakeTransparent(Resources.Folder);
|
||||||
|
_closed = MakeTransparent(Resources.FolderClosed);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Image MakeTransparent(Bitmap bitmap)
|
||||||
|
{
|
||||||
|
bitmap.MakeTransparent(bitmap.GetPixel(0,0));
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Image GetIcon(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
Image icon = base.GetIcon(node);
|
||||||
|
if (icon != null)
|
||||||
|
return icon;
|
||||||
|
else if (node.IsLeaf)
|
||||||
|
return _leaf;
|
||||||
|
else if (node.CanExpand && node.IsExpanded)
|
||||||
|
return _opened;
|
||||||
|
else
|
||||||
|
return _closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree.NodeControls
|
||||||
|
{
|
||||||
|
public class NodeTextBox : BaseTextControl
|
||||||
|
{
|
||||||
|
private const int MinTextBoxWidth = 30;
|
||||||
|
|
||||||
|
public NodeTextBox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Size CalculateEditorSize(EditorContext context)
|
||||||
|
{
|
||||||
|
if (Parent.UseColumns)
|
||||||
|
return context.Bounds.Size;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Size size = GetLabelSize(context.CurrentNode, context.DrawContext, _label);
|
||||||
|
int width = Math.Max(size.Width + Font.Height, MinTextBoxWidth); // reserve a place for new typed character
|
||||||
|
return new Size(width, size.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void KeyDown(KeyEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.KeyCode == Keys.F2 && Parent.CurrentNode != null && EditEnabled)
|
||||||
|
{
|
||||||
|
args.Handled = true;
|
||||||
|
BeginEdit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Control CreateEditor(TreeNodeAdv node)
|
||||||
|
{
|
||||||
|
TextBox textBox = CreateTextBox();
|
||||||
|
textBox.TextAlign = TextAlign;
|
||||||
|
textBox.Text = GetLabel(node);
|
||||||
|
textBox.BorderStyle = BorderStyle.FixedSingle;
|
||||||
|
textBox.TextChanged += EditorTextChanged;
|
||||||
|
textBox.KeyDown += EditorKeyDown;
|
||||||
|
_label = textBox.Text;
|
||||||
|
SetEditControlProperties(textBox, node);
|
||||||
|
return textBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual TextBox CreateTextBox()
|
||||||
|
{
|
||||||
|
return new TextBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DisposeEditor(Control editor)
|
||||||
|
{
|
||||||
|
var textBox = editor as TextBox;
|
||||||
|
textBox.TextChanged -= EditorTextChanged;
|
||||||
|
textBox.KeyDown -= EditorKeyDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EditorKeyDown(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.KeyCode == Keys.Escape)
|
||||||
|
EndEdit(false);
|
||||||
|
else if (e.KeyCode == Keys.Enter)
|
||||||
|
EndEdit(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _label;
|
||||||
|
private void EditorTextChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var textBox = sender as TextBox;
|
||||||
|
_label = textBox.Text;
|
||||||
|
Parent.UpdateEditorBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
|
||||||
|
{
|
||||||
|
var label = (editor as TextBox).Text;
|
||||||
|
string oldLabel = GetLabel(node);
|
||||||
|
if (oldLabel != label)
|
||||||
|
{
|
||||||
|
SetLabel(node, label);
|
||||||
|
OnLabelChanged(node.Tag, oldLabel, label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Cut(Control control)
|
||||||
|
{
|
||||||
|
(control as TextBox).Cut();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Copy(Control control)
|
||||||
|
{
|
||||||
|
(control as TextBox).Copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Paste(Control control)
|
||||||
|
{
|
||||||
|
(control as TextBox).Paste();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Delete(Control control)
|
||||||
|
{
|
||||||
|
var textBox = control as TextBox;
|
||||||
|
int len = Math.Max(textBox.SelectionLength, 1);
|
||||||
|
if (textBox.SelectionStart < textBox.Text.Length)
|
||||||
|
{
|
||||||
|
int start = textBox.SelectionStart;
|
||||||
|
textBox.Text = textBox.Text.Remove(textBox.SelectionStart, len);
|
||||||
|
textBox.SelectionStart = start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<LabelEventArgs> LabelChanged;
|
||||||
|
protected void OnLabelChanged(object subject, string oldLabel, string newLabel)
|
||||||
|
{
|
||||||
|
if (LabelChanged != null)
|
||||||
|
LabelChanged(this, new LabelEventArgs(subject, oldLabel, newLabel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class SortedTreeModel: TreeModelBase
|
||||||
|
{
|
||||||
|
private ITreeModel _innerModel;
|
||||||
|
public ITreeModel InnerModel
|
||||||
|
{
|
||||||
|
get { return _innerModel; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private IComparer _comparer;
|
||||||
|
public IComparer Comparer
|
||||||
|
{
|
||||||
|
get { return _comparer; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_comparer = value;
|
||||||
|
OnStructureChanged(new TreePathEventArgs(TreePath.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortedTreeModel(ITreeModel innerModel)
|
||||||
|
{
|
||||||
|
_innerModel = innerModel;
|
||||||
|
_innerModel.NodesChanged += new EventHandler<TreeModelEventArgs>(_innerModel_NodesChanged);
|
||||||
|
_innerModel.NodesInserted += new EventHandler<TreeModelEventArgs>(_innerModel_NodesInserted);
|
||||||
|
_innerModel.NodesRemoved += new EventHandler<TreeModelEventArgs>(_innerModel_NodesRemoved);
|
||||||
|
_innerModel.StructureChanged += new EventHandler<TreePathEventArgs>(_innerModel_StructureChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _innerModel_StructureChanged(object sender, TreePathEventArgs e)
|
||||||
|
{
|
||||||
|
OnStructureChanged(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _innerModel_NodesRemoved(object sender, TreeModelEventArgs e)
|
||||||
|
{
|
||||||
|
OnStructureChanged(new TreePathEventArgs(e.Path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _innerModel_NodesInserted(object sender, TreeModelEventArgs e)
|
||||||
|
{
|
||||||
|
OnStructureChanged(new TreePathEventArgs(e.Path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _innerModel_NodesChanged(object sender, TreeModelEventArgs e)
|
||||||
|
{
|
||||||
|
OnStructureChanged(new TreePathEventArgs(e.Path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable GetChildren(TreePath treePath)
|
||||||
|
{
|
||||||
|
if (Comparer != null)
|
||||||
|
{
|
||||||
|
ArrayList list = new ArrayList();
|
||||||
|
IEnumerable res = InnerModel.GetChildren(treePath);
|
||||||
|
if (res != null)
|
||||||
|
{
|
||||||
|
foreach (object obj in res)
|
||||||
|
list.Add(obj);
|
||||||
|
list.Sort(Comparer);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return InnerModel.GetChildren(treePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsLeaf(TreePath treePath)
|
||||||
|
{
|
||||||
|
return InnerModel.IsLeaf(treePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
385
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/TreeColumn.cs
Normal file
@@ -0,0 +1,385 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms.VisualStyles;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
[TypeConverter(typeof(TreeColumn.TreeColumnConverter)), DesignTimeVisible(false), ToolboxItem(false)]
|
||||||
|
public class TreeColumn : Component
|
||||||
|
{
|
||||||
|
private class TreeColumnConverter : ComponentConverter
|
||||||
|
{
|
||||||
|
public TreeColumnConverter()
|
||||||
|
: base(typeof(TreeColumn))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool GetPropertiesSupported(ITypeDescriptorContext context)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const int HeaderLeftMargin = 5;
|
||||||
|
private const int HeaderRightMargin = 5;
|
||||||
|
private const int SortOrderMarkMargin = 8;
|
||||||
|
|
||||||
|
private TextFormatFlags _headerFlags;
|
||||||
|
private TextFormatFlags _baseHeaderFlags = TextFormatFlags.NoPadding |
|
||||||
|
TextFormatFlags.EndEllipsis |
|
||||||
|
TextFormatFlags.VerticalCenter |
|
||||||
|
TextFormatFlags.PreserveGraphicsTranslateTransform;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private TreeColumnCollection _owner;
|
||||||
|
internal TreeColumnCollection Owner
|
||||||
|
{
|
||||||
|
get { return _owner; }
|
||||||
|
set { _owner = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public int Index
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Owner != null)
|
||||||
|
return Owner.IndexOf(this);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _header;
|
||||||
|
[Localizable(true)]
|
||||||
|
public string Header
|
||||||
|
{
|
||||||
|
get { return _header; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_header = value;
|
||||||
|
OnHeaderChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _tooltipText;
|
||||||
|
[Localizable(true)]
|
||||||
|
public string TooltipText
|
||||||
|
{
|
||||||
|
get { return _tooltipText; }
|
||||||
|
set { _tooltipText = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _width;
|
||||||
|
[DefaultValue(50), Localizable(true)]
|
||||||
|
public int Width
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _width;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_width != value)
|
||||||
|
{
|
||||||
|
_width = Math.Max(MinColumnWidth, value);
|
||||||
|
if (_maxColumnWidth > 0)
|
||||||
|
{
|
||||||
|
_width = Math.Min(_width, MaxColumnWidth);
|
||||||
|
}
|
||||||
|
OnWidthChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _minColumnWidth;
|
||||||
|
[DefaultValue(0)]
|
||||||
|
public int MinColumnWidth
|
||||||
|
{
|
||||||
|
get { return _minColumnWidth; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
throw new ArgumentOutOfRangeException("value");
|
||||||
|
|
||||||
|
_minColumnWidth = value;
|
||||||
|
Width = Math.Max(value, Width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _maxColumnWidth;
|
||||||
|
[DefaultValue(0)]
|
||||||
|
public int MaxColumnWidth
|
||||||
|
{
|
||||||
|
get { return _maxColumnWidth; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
throw new ArgumentOutOfRangeException("value");
|
||||||
|
|
||||||
|
_maxColumnWidth = value;
|
||||||
|
if (value > 0)
|
||||||
|
Width = Math.Min(value, _width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _visible = true;
|
||||||
|
[DefaultValue(true)]
|
||||||
|
public bool IsVisible
|
||||||
|
{
|
||||||
|
get { return _visible; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_visible = value;
|
||||||
|
OnIsVisibleChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HorizontalAlignment _textAlign = HorizontalAlignment.Left;
|
||||||
|
[DefaultValue(HorizontalAlignment.Left)]
|
||||||
|
public HorizontalAlignment TextAlign
|
||||||
|
{
|
||||||
|
get { return _textAlign; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _textAlign)
|
||||||
|
{
|
||||||
|
_textAlign = value;
|
||||||
|
_headerFlags = _baseHeaderFlags | TextHelper.TranslateAligmentToFlag(value);
|
||||||
|
OnHeaderChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _sortable = false;
|
||||||
|
[DefaultValue(false)]
|
||||||
|
public bool Sortable
|
||||||
|
{
|
||||||
|
get { return _sortable; }
|
||||||
|
set { _sortable = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private SortOrder _sort_order = SortOrder.None;
|
||||||
|
public SortOrder SortOrder
|
||||||
|
{
|
||||||
|
get { return _sort_order; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == _sort_order)
|
||||||
|
return;
|
||||||
|
_sort_order = value;
|
||||||
|
OnSortOrderChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size SortMarkSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Application.RenderWithVisualStyles)
|
||||||
|
return new Size(9, 5);
|
||||||
|
else
|
||||||
|
return new Size(7, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public TreeColumn():
|
||||||
|
this(string.Empty, 50)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeColumn(string header, int width)
|
||||||
|
{
|
||||||
|
_header = header;
|
||||||
|
_width = width;
|
||||||
|
_headerFlags = _baseHeaderFlags | TextFormatFlags.Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(Header))
|
||||||
|
return GetType().Name;
|
||||||
|
else
|
||||||
|
return Header;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Draw
|
||||||
|
|
||||||
|
private static VisualStyleRenderer _normalRenderer;
|
||||||
|
private static VisualStyleRenderer _pressedRenderer;
|
||||||
|
private static VisualStyleRenderer _hotRenderer;
|
||||||
|
|
||||||
|
private static void CreateRenderers()
|
||||||
|
{
|
||||||
|
if (Application.RenderWithVisualStyles && _normalRenderer == null)
|
||||||
|
{
|
||||||
|
_normalRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Normal);
|
||||||
|
_pressedRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Pressed);
|
||||||
|
_hotRenderer = new VisualStyleRenderer(VisualStyleElement.Header.Item.Hot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Bitmap CreateGhostImage(Rectangle bounds, Font font)
|
||||||
|
{
|
||||||
|
Bitmap b = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format32bppArgb);
|
||||||
|
Graphics gr = Graphics.FromImage(b);
|
||||||
|
gr.FillRectangle(SystemBrushes.ControlDark, bounds);
|
||||||
|
DrawContent(gr, bounds, font);
|
||||||
|
BitmapHelper.SetAlphaChanelValue(b, 150);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Draw(Graphics gr, Rectangle bounds, Font font, bool pressed, bool hot)
|
||||||
|
{
|
||||||
|
DrawBackground(gr, bounds, pressed, hot);
|
||||||
|
DrawContent(gr, bounds, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawContent(Graphics gr, Rectangle bounds, Font font)
|
||||||
|
{
|
||||||
|
if (TreeViewAdv.CustomColumnTextRenderFunc != null)
|
||||||
|
{
|
||||||
|
TreeViewAdv.CustomColumnTextRenderFunc(gr, bounds, font, Header);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Rectangle innerBounds = new Rectangle(bounds.X + HeaderLeftMargin, bounds.Y,
|
||||||
|
bounds.Width - HeaderLeftMargin - HeaderRightMargin,
|
||||||
|
bounds.Height);
|
||||||
|
|
||||||
|
if (SortOrder != SortOrder.None)
|
||||||
|
innerBounds.Width -= (SortMarkSize.Width + SortOrderMarkMargin);
|
||||||
|
|
||||||
|
Size maxTextSize = TextRenderer.MeasureText(gr, Header, font, innerBounds.Size, TextFormatFlags.NoPadding);
|
||||||
|
Size textSize = TextRenderer.MeasureText(gr, Header, font, innerBounds.Size, _baseHeaderFlags);
|
||||||
|
|
||||||
|
if (SortOrder != SortOrder.None)
|
||||||
|
{
|
||||||
|
int tw = Math.Min(textSize.Width, innerBounds.Size.Width);
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
if (TextAlign == HorizontalAlignment.Left)
|
||||||
|
x = innerBounds.X + tw + SortOrderMarkMargin;
|
||||||
|
else if (TextAlign == HorizontalAlignment.Right)
|
||||||
|
x = innerBounds.Right + SortOrderMarkMargin;
|
||||||
|
else
|
||||||
|
x = innerBounds.X + tw + (innerBounds.Width - tw) / 2 + SortOrderMarkMargin;
|
||||||
|
DrawSortMark(gr, bounds, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textSize.Width < maxTextSize.Width)
|
||||||
|
TextRenderer.DrawText(gr, Header, font, innerBounds, SystemColors.ControlText, _baseHeaderFlags | TextFormatFlags.Left);
|
||||||
|
else
|
||||||
|
TextRenderer.DrawText(gr, Header, font, innerBounds, SystemColors.ControlText, _headerFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawSortMark(Graphics gr, Rectangle bounds, int x)
|
||||||
|
{
|
||||||
|
int y = bounds.Y + bounds.Height / 2 - 2;
|
||||||
|
x = Math.Max(x, bounds.X + SortOrderMarkMargin);
|
||||||
|
|
||||||
|
int w2 = SortMarkSize.Width / 2;
|
||||||
|
if (SortOrder == SortOrder.Ascending)
|
||||||
|
{
|
||||||
|
Point[] points = new Point[] { new Point(x, y), new Point(x + SortMarkSize.Width, y), new Point(x + w2, y + SortMarkSize.Height) };
|
||||||
|
gr.FillPolygon(SystemBrushes.ControlDark, points);
|
||||||
|
}
|
||||||
|
else if (SortOrder == SortOrder.Descending)
|
||||||
|
{
|
||||||
|
Point[] points = new Point[] { new Point(x - 1, y + SortMarkSize.Height), new Point(x + SortMarkSize.Width, y + SortMarkSize.Height), new Point(x + w2, y - 1) };
|
||||||
|
gr.FillPolygon(SystemBrushes.ControlDark, points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DrawDropMark(Graphics gr, Rectangle rect)
|
||||||
|
{
|
||||||
|
gr.FillRectangle(SystemBrushes.HotTrack, rect.X-1, rect.Y, 2, rect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void DrawBackground(Graphics gr, Rectangle bounds, bool pressed, bool hot)
|
||||||
|
{
|
||||||
|
if (TreeViewAdv.CustomColumnBackgroundRenderFunc != null)
|
||||||
|
{
|
||||||
|
TreeViewAdv.CustomColumnBackgroundRenderFunc(gr, bounds, pressed, hot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Application.RenderWithVisualStyles)
|
||||||
|
{
|
||||||
|
CreateRenderers();
|
||||||
|
if (pressed)
|
||||||
|
_pressedRenderer.DrawBackground(gr, bounds);
|
||||||
|
else if (hot)
|
||||||
|
_hotRenderer.DrawBackground(gr, bounds);
|
||||||
|
else
|
||||||
|
_normalRenderer.DrawBackground(gr, bounds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gr.FillRectangle(SystemBrushes.Control, bounds);
|
||||||
|
Pen p1 = SystemPens.ControlLightLight;
|
||||||
|
Pen p2 = SystemPens.ControlDark;
|
||||||
|
Pen p3 = SystemPens.ControlDarkDark;
|
||||||
|
if (pressed)
|
||||||
|
gr.DrawRectangle(p2, bounds.X, bounds.Y, bounds.Width, bounds.Height);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gr.DrawLine(p1, bounds.X, bounds.Y, bounds.Right, bounds.Y);
|
||||||
|
gr.DrawLine(p3, bounds.X, bounds.Bottom, bounds.Right, bounds.Bottom);
|
||||||
|
gr.DrawLine(p3, bounds.Right - 1, bounds.Y, bounds.Right - 1, bounds.Bottom - 1);
|
||||||
|
gr.DrawLine(p1, bounds.Left, bounds.Y + 1, bounds.Left, bounds.Bottom - 2);
|
||||||
|
gr.DrawLine(p2, bounds.Right - 2, bounds.Y + 1, bounds.Right - 2, bounds.Bottom - 2);
|
||||||
|
gr.DrawLine(p2, bounds.X, bounds.Bottom - 1, bounds.Right - 2, bounds.Bottom - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
public event EventHandler HeaderChanged;
|
||||||
|
private void OnHeaderChanged()
|
||||||
|
{
|
||||||
|
if (HeaderChanged != null)
|
||||||
|
HeaderChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler SortOrderChanged;
|
||||||
|
private void OnSortOrderChanged()
|
||||||
|
{
|
||||||
|
if (SortOrderChanged != null)
|
||||||
|
SortOrderChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler IsVisibleChanged;
|
||||||
|
private void OnIsVisibleChanged()
|
||||||
|
{
|
||||||
|
if (IsVisibleChanged != null)
|
||||||
|
IsVisibleChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler WidthChanged;
|
||||||
|
private void OnWidthChanged()
|
||||||
|
{
|
||||||
|
if (WidthChanged != null)
|
||||||
|
WidthChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
internal class TreeColumnCollection : Collection<TreeColumn>
|
||||||
|
{
|
||||||
|
private TreeViewAdv _treeView;
|
||||||
|
|
||||||
|
public TreeColumnCollection(TreeViewAdv treeView)
|
||||||
|
{
|
||||||
|
_treeView = treeView;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InsertItem(int index, TreeColumn item)
|
||||||
|
{
|
||||||
|
base.InsertItem(index, item);
|
||||||
|
BindEvents(item);
|
||||||
|
_treeView.UpdateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RemoveItem(int index)
|
||||||
|
{
|
||||||
|
UnbindEvents(this[index]);
|
||||||
|
base.RemoveItem(index);
|
||||||
|
_treeView.UpdateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetItem(int index, TreeColumn item)
|
||||||
|
{
|
||||||
|
UnbindEvents(this[index]);
|
||||||
|
base.SetItem(index, item);
|
||||||
|
item.Owner = this;
|
||||||
|
BindEvents(item);
|
||||||
|
_treeView.UpdateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ClearItems()
|
||||||
|
{
|
||||||
|
foreach (TreeColumn c in Items)
|
||||||
|
UnbindEvents(c);
|
||||||
|
Items.Clear();
|
||||||
|
_treeView.UpdateColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindEvents(TreeColumn item)
|
||||||
|
{
|
||||||
|
item.Owner = this;
|
||||||
|
item.HeaderChanged += HeaderChanged;
|
||||||
|
item.IsVisibleChanged += IsVisibleChanged;
|
||||||
|
item.WidthChanged += WidthChanged;
|
||||||
|
item.SortOrderChanged += SortOrderChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UnbindEvents(TreeColumn item)
|
||||||
|
{
|
||||||
|
item.Owner = null;
|
||||||
|
item.HeaderChanged -= HeaderChanged;
|
||||||
|
item.IsVisibleChanged -= IsVisibleChanged;
|
||||||
|
item.WidthChanged -= WidthChanged;
|
||||||
|
item.SortOrderChanged -= SortOrderChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SortOrderChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
TreeColumn changed = sender as TreeColumn;
|
||||||
|
//Only one column at a time can have a sort property set
|
||||||
|
if (changed.SortOrder != SortOrder.None)
|
||||||
|
{
|
||||||
|
foreach (TreeColumn col in this)
|
||||||
|
{
|
||||||
|
if (col != changed)
|
||||||
|
col.SortOrder = SortOrder.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_treeView.UpdateHeaders();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WidthChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_treeView.ChangeColumnWidth(sender as TreeColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IsVisibleChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_treeView.FullUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeaderChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_treeView.UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class TreeColumnEventArgs: EventArgs
|
||||||
|
{
|
||||||
|
private TreeColumn _column;
|
||||||
|
public TreeColumn Column
|
||||||
|
{
|
||||||
|
get { return _column; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeColumnEventArgs(TreeColumn column)
|
||||||
|
{
|
||||||
|
_column = column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts IEnumerable interface to ITreeModel.
|
||||||
|
/// Allows to display a plain list in the TreeView
|
||||||
|
/// </summary>
|
||||||
|
public class TreeListAdapter : ITreeModel
|
||||||
|
{
|
||||||
|
private System.Collections.IEnumerable _list;
|
||||||
|
|
||||||
|
public TreeListAdapter(System.Collections.IEnumerable list)
|
||||||
|
{
|
||||||
|
_list = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ITreeModel Members
|
||||||
|
|
||||||
|
public System.Collections.IEnumerable GetChildren(TreePath treePath)
|
||||||
|
{
|
||||||
|
if (treePath.IsEmpty())
|
||||||
|
return _list;
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLeaf(TreePath treePath)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesChanged;
|
||||||
|
public void OnNodesChanged(TreeModelEventArgs args)
|
||||||
|
{
|
||||||
|
if (NodesChanged != null)
|
||||||
|
NodesChanged(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreePathEventArgs> StructureChanged;
|
||||||
|
public void OnStructureChanged(TreePathEventArgs args)
|
||||||
|
{
|
||||||
|
if (StructureChanged != null)
|
||||||
|
StructureChanged(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesInserted;
|
||||||
|
public void OnNodeInserted(TreeModelEventArgs args)
|
||||||
|
{
|
||||||
|
if (NodesInserted != null)
|
||||||
|
NodesInserted(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesRemoved;
|
||||||
|
public void OnNodeRemoved(TreeModelEventArgs args)
|
||||||
|
{
|
||||||
|
if (NodesRemoved != null)
|
||||||
|
NodesRemoved(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
127
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/TreeModel.cs
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a simple ready to use implementation of <see cref="ITreeModel"/>. Warning: this class is not optimized
|
||||||
|
/// to work with big amount of data. In this case create you own implementation of <c>ITreeModel</c>, and pay attention
|
||||||
|
/// on GetChildren and IsLeaf methods.
|
||||||
|
/// </summary>
|
||||||
|
public class TreeModel : ITreeModel
|
||||||
|
{
|
||||||
|
private Node _root;
|
||||||
|
public Node Root
|
||||||
|
{
|
||||||
|
get { return _root; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Node> Nodes
|
||||||
|
{
|
||||||
|
get { return _root.Nodes; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeModel()
|
||||||
|
{
|
||||||
|
_root = new Node();
|
||||||
|
_root.Model = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePath GetPath(Node node)
|
||||||
|
{
|
||||||
|
if (node == _root)
|
||||||
|
return TreePath.Empty;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Stack<object> stack = new Stack<object>();
|
||||||
|
while (node != _root)
|
||||||
|
{
|
||||||
|
stack.Push(node);
|
||||||
|
node = node.Parent;
|
||||||
|
}
|
||||||
|
return new TreePath(stack.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node FindNode(TreePath path)
|
||||||
|
{
|
||||||
|
if (path.IsEmpty())
|
||||||
|
return _root;
|
||||||
|
else
|
||||||
|
return FindNode(_root, path, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node FindNode(Node root, TreePath path, int level)
|
||||||
|
{
|
||||||
|
foreach (Node node in root.Nodes)
|
||||||
|
if (node == path.FullPath[level])
|
||||||
|
{
|
||||||
|
if (level == path.FullPath.Length - 1)
|
||||||
|
return node;
|
||||||
|
else
|
||||||
|
return FindNode(node, path, level + 1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ITreeModel Members
|
||||||
|
|
||||||
|
public System.Collections.IEnumerable GetChildren(TreePath treePath)
|
||||||
|
{
|
||||||
|
Node node = FindNode(treePath);
|
||||||
|
if (node != null)
|
||||||
|
foreach (Node n in node.Nodes)
|
||||||
|
yield return n;
|
||||||
|
else
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLeaf(TreePath treePath)
|
||||||
|
{
|
||||||
|
Node node = FindNode(treePath);
|
||||||
|
if (node != null)
|
||||||
|
return node.IsLeaf;
|
||||||
|
else
|
||||||
|
throw new ArgumentException("treePath");
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesChanged;
|
||||||
|
internal void OnNodesChanged(TreeModelEventArgs args)
|
||||||
|
{
|
||||||
|
if (NodesChanged != null)
|
||||||
|
NodesChanged(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreePathEventArgs> StructureChanged;
|
||||||
|
public void OnStructureChanged(TreePathEventArgs args)
|
||||||
|
{
|
||||||
|
if (StructureChanged != null)
|
||||||
|
StructureChanged(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesInserted;
|
||||||
|
internal void OnNodeInserted(Node parent, int index, Node node)
|
||||||
|
{
|
||||||
|
if (NodesInserted != null)
|
||||||
|
{
|
||||||
|
TreeModelEventArgs args = new TreeModelEventArgs(GetPath(parent), new int[] { index }, new object[] { node });
|
||||||
|
NodesInserted(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesRemoved;
|
||||||
|
internal void OnNodeRemoved(Node parent, int index, Node node)
|
||||||
|
{
|
||||||
|
if (NodesRemoved != null)
|
||||||
|
{
|
||||||
|
TreeModelEventArgs args = new TreeModelEventArgs(GetPath(parent), new int[] { index }, new object[] { node });
|
||||||
|
NodesRemoved(this, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public abstract class TreeModelBase: ITreeModel
|
||||||
|
{
|
||||||
|
public abstract System.Collections.IEnumerable GetChildren(TreePath treePath);
|
||||||
|
public abstract bool IsLeaf(TreePath treePath);
|
||||||
|
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesChanged;
|
||||||
|
protected void OnNodesChanged(TreeModelEventArgs args)
|
||||||
|
{
|
||||||
|
if (NodesChanged != null)
|
||||||
|
NodesChanged(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreePathEventArgs> StructureChanged;
|
||||||
|
protected void OnStructureChanged(TreePathEventArgs args)
|
||||||
|
{
|
||||||
|
if (StructureChanged != null)
|
||||||
|
StructureChanged(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesInserted;
|
||||||
|
protected void OnNodesInserted(TreeModelEventArgs args)
|
||||||
|
{
|
||||||
|
if (NodesInserted != null)
|
||||||
|
NodesInserted(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeModelEventArgs> NodesRemoved;
|
||||||
|
protected void OnNodesRemoved(TreeModelEventArgs args)
|
||||||
|
{
|
||||||
|
if (NodesRemoved != null)
|
||||||
|
NodesRemoved(this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Refresh()
|
||||||
|
{
|
||||||
|
OnStructureChanged(new TreePathEventArgs(TreePath.Empty));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class TreeModelEventArgs: TreePathEventArgs
|
||||||
|
{
|
||||||
|
private object[] _children;
|
||||||
|
public object[] Children
|
||||||
|
{
|
||||||
|
get { return _children; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int[] _indices;
|
||||||
|
public int[] Indices
|
||||||
|
{
|
||||||
|
get { return _indices; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parent">Path to a parent node</param>
|
||||||
|
/// <param name="children">Child nodes</param>
|
||||||
|
public TreeModelEventArgs(TreePath parent, object[] children)
|
||||||
|
: this(parent, null, children)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parent">Path to a parent node</param>
|
||||||
|
/// <param name="indices">Indices of children in parent nodes collection</param>
|
||||||
|
/// <param name="children">Child nodes</param>
|
||||||
|
public TreeModelEventArgs(TreePath parent, int[] indices, object[] children)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
if (children == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
if (indices != null && indices.Length != children.Length)
|
||||||
|
throw new ArgumentException("indices and children arrays must have the same length");
|
||||||
|
|
||||||
|
_indices = indices;
|
||||||
|
_children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
443
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/TreeNodeAdv.cs
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Security.Permissions;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public sealed class TreeNodeAdv : ISerializable
|
||||||
|
{
|
||||||
|
#region NodeCollection
|
||||||
|
private class NodeCollection : Collection<TreeNodeAdv>
|
||||||
|
{
|
||||||
|
private TreeNodeAdv _owner;
|
||||||
|
|
||||||
|
public NodeCollection(TreeNodeAdv owner)
|
||||||
|
{
|
||||||
|
_owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ClearItems()
|
||||||
|
{
|
||||||
|
while (this.Count != 0)
|
||||||
|
this.RemoveAt(this.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InsertItem(int index, TreeNodeAdv item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
|
||||||
|
if (item.Parent != _owner)
|
||||||
|
{
|
||||||
|
if (item.Parent != null)
|
||||||
|
item.Parent.Nodes.Remove(item);
|
||||||
|
item._parent = _owner;
|
||||||
|
item._index = index;
|
||||||
|
for (int i = index; i < Count; i++)
|
||||||
|
this[i]._index++;
|
||||||
|
base.InsertItem(index, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_owner.Tree != null && _owner.Tree.Model == null)
|
||||||
|
{
|
||||||
|
_owner.Tree.SmartFullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RemoveItem(int index)
|
||||||
|
{
|
||||||
|
TreeNodeAdv item = this[index];
|
||||||
|
item._parent = null;
|
||||||
|
item._index = -1;
|
||||||
|
for (int i = index + 1; i < Count; i++)
|
||||||
|
this[i]._index--;
|
||||||
|
base.RemoveItem(index);
|
||||||
|
|
||||||
|
if (_owner.Tree != null && _owner.Tree.Model == null)
|
||||||
|
{
|
||||||
|
_owner.Tree.UpdateSelection();
|
||||||
|
_owner.Tree.SmartFullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void SetItem(int index, TreeNodeAdv item)
|
||||||
|
{
|
||||||
|
if (item == null)
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
RemoveAt(index);
|
||||||
|
InsertItem(index, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
public event EventHandler<TreeViewAdvEventArgs> Collapsing;
|
||||||
|
internal void OnCollapsing()
|
||||||
|
{
|
||||||
|
if (Collapsing != null)
|
||||||
|
Collapsing(this, new TreeViewAdvEventArgs(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeViewAdvEventArgs> Collapsed;
|
||||||
|
internal void OnCollapsed()
|
||||||
|
{
|
||||||
|
if (Collapsed != null)
|
||||||
|
Collapsed(this, new TreeViewAdvEventArgs(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeViewAdvEventArgs> Expanding;
|
||||||
|
internal void OnExpanding()
|
||||||
|
{
|
||||||
|
if (Expanding != null)
|
||||||
|
Expanding(this, new TreeViewAdvEventArgs(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<TreeViewAdvEventArgs> Expanded;
|
||||||
|
internal void OnExpanded()
|
||||||
|
{
|
||||||
|
if (Expanded != null)
|
||||||
|
Expanded(this, new TreeViewAdvEventArgs(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
private TreeViewAdv _tree;
|
||||||
|
public TreeViewAdv Tree
|
||||||
|
{
|
||||||
|
get { return _tree; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _row;
|
||||||
|
public int Row
|
||||||
|
{
|
||||||
|
get { return _row; }
|
||||||
|
internal set { _row = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _index = -1;
|
||||||
|
public int Index
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isSelected;
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get { return _isSelected; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_isSelected != value)
|
||||||
|
{
|
||||||
|
if (Tree.IsMyNode(this))
|
||||||
|
{
|
||||||
|
//_tree.OnSelectionChanging
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
if (!_tree.Selection.Contains(this))
|
||||||
|
_tree.Selection.Add(this);
|
||||||
|
|
||||||
|
if (_tree.Selection.Count == 1)
|
||||||
|
_tree.CurrentNode = this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_tree.Selection.Remove(this);
|
||||||
|
_tree.UpdateView();
|
||||||
|
_tree.OnSelectionChanged();
|
||||||
|
}
|
||||||
|
_isSelected = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if all parent nodes of this node are expanded.
|
||||||
|
/// </summary>
|
||||||
|
internal bool IsVisible
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TreeNodeAdv node = _parent;
|
||||||
|
while (node != null)
|
||||||
|
{
|
||||||
|
if (!node.IsExpanded)
|
||||||
|
return false;
|
||||||
|
node = node.Parent;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isLeaf;
|
||||||
|
public bool IsLeaf
|
||||||
|
{
|
||||||
|
get { return _isLeaf; }
|
||||||
|
internal set { _isLeaf = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isExpandedOnce;
|
||||||
|
public bool IsExpandedOnce
|
||||||
|
{
|
||||||
|
get { return _isExpandedOnce; }
|
||||||
|
internal set { _isExpandedOnce = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isExpanded;
|
||||||
|
public bool IsExpanded
|
||||||
|
{
|
||||||
|
get { return _isExpanded; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
Expand();
|
||||||
|
else
|
||||||
|
Collapse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AssignIsExpanded(bool value)
|
||||||
|
{
|
||||||
|
_isExpanded = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNodeAdv _parent;
|
||||||
|
public TreeNodeAdv Parent
|
||||||
|
{
|
||||||
|
get { return _parent; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Level
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_parent == null)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return _parent.Level + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeNodeAdv PreviousNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_parent != null)
|
||||||
|
{
|
||||||
|
int index = Index;
|
||||||
|
if (index > 0)
|
||||||
|
return _parent.Nodes[index - 1];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeNodeAdv NextNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_parent != null)
|
||||||
|
{
|
||||||
|
int index = Index;
|
||||||
|
if (index < _parent.Nodes.Count - 1)
|
||||||
|
return _parent.Nodes[index + 1];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TreeNodeAdv BottomNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TreeNodeAdv parent = this.Parent;
|
||||||
|
if (parent != null)
|
||||||
|
{
|
||||||
|
if (parent.NextNode != null)
|
||||||
|
return parent.NextNode;
|
||||||
|
else
|
||||||
|
return parent.BottomNode;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TreeNodeAdv NextVisibleNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IsExpanded && Nodes.Count > 0)
|
||||||
|
return Nodes[0];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TreeNodeAdv nn = NextNode;
|
||||||
|
if (nn != null)
|
||||||
|
return nn;
|
||||||
|
else
|
||||||
|
return BottomNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanExpand
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (Nodes.Count > 0 || (!IsExpandedOnce && !IsLeaf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object _tag;
|
||||||
|
public object Tag
|
||||||
|
{
|
||||||
|
get { return _tag; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<TreeNodeAdv> _nodes;
|
||||||
|
internal Collection<TreeNodeAdv> Nodes
|
||||||
|
{
|
||||||
|
get { return _nodes; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReadOnlyCollection<TreeNodeAdv> _children;
|
||||||
|
public ReadOnlyCollection<TreeNodeAdv> Children
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int? _rightBounds;
|
||||||
|
internal int? RightBounds
|
||||||
|
{
|
||||||
|
get { return _rightBounds; }
|
||||||
|
set { _rightBounds = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int? _height;
|
||||||
|
internal int? Height
|
||||||
|
{
|
||||||
|
get { return _height; }
|
||||||
|
set { _height = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isExpandingNow;
|
||||||
|
internal bool IsExpandingNow
|
||||||
|
{
|
||||||
|
get { return _isExpandingNow; }
|
||||||
|
set { _isExpandingNow = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _autoExpandOnStructureChanged = true;
|
||||||
|
public bool AutoExpandOnStructureChanged
|
||||||
|
{
|
||||||
|
get { return _autoExpandOnStructureChanged; }
|
||||||
|
set { _autoExpandOnStructureChanged = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public TreeNodeAdv(object tag)
|
||||||
|
: this(null, tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TreeNodeAdv(TreeViewAdv tree, object tag)
|
||||||
|
{
|
||||||
|
_row = -1;
|
||||||
|
_tree = tree;
|
||||||
|
_nodes = new NodeCollection(this);
|
||||||
|
_children = new ReadOnlyCollection<TreeNodeAdv>(_nodes);
|
||||||
|
_tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
if (Tag != null)
|
||||||
|
return Tag.ToString();
|
||||||
|
else
|
||||||
|
return base.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Collapse()
|
||||||
|
{
|
||||||
|
if (_isExpanded)
|
||||||
|
Collapse(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CollapseAll()
|
||||||
|
{
|
||||||
|
Collapse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Collapse(bool ignoreChildren)
|
||||||
|
{
|
||||||
|
SetIsExpanded(false, ignoreChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Expand()
|
||||||
|
{
|
||||||
|
if (!_isExpanded)
|
||||||
|
Expand(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExpandAll()
|
||||||
|
{
|
||||||
|
Expand(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Expand(bool ignoreChildren)
|
||||||
|
{
|
||||||
|
SetIsExpanded(true, ignoreChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetIsExpanded(bool value, bool ignoreChildren)
|
||||||
|
{
|
||||||
|
if (Tree == null)
|
||||||
|
_isExpanded = value;
|
||||||
|
else
|
||||||
|
Tree.SetIsExpanded(this, value, ignoreChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ISerializable Members
|
||||||
|
|
||||||
|
private TreeNodeAdv(SerializationInfo info, StreamingContext context)
|
||||||
|
: this(null, null)
|
||||||
|
{
|
||||||
|
int nodesCount = 0;
|
||||||
|
nodesCount = info.GetInt32("NodesCount");
|
||||||
|
_isExpanded = info.GetBoolean("IsExpanded");
|
||||||
|
_tag = info.GetValue("Tag", typeof(object));
|
||||||
|
|
||||||
|
for (int i = 0; i < nodesCount; i++)
|
||||||
|
{
|
||||||
|
TreeNodeAdv child = (TreeNodeAdv)info.GetValue("Child" + i, typeof(TreeNodeAdv));
|
||||||
|
Nodes.Add(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
|
||||||
|
public void GetObjectData(SerializationInfo info, StreamingContext context)
|
||||||
|
{
|
||||||
|
info.AddValue("IsExpanded", IsExpanded);
|
||||||
|
info.AddValue("NodesCount", Nodes.Count);
|
||||||
|
if ((Tag != null) && Tag.GetType().IsSerializable)
|
||||||
|
info.AddValue("Tag", Tag, Tag.GetType());
|
||||||
|
|
||||||
|
for (int i = 0; i < Nodes.Count; i++)
|
||||||
|
info.AddValue("Child" + i, Nodes[i], typeof(TreeNodeAdv));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class TreeNodeAdvMouseEventArgs : MouseEventArgs
|
||||||
|
{
|
||||||
|
private TreeNodeAdv _node;
|
||||||
|
public TreeNodeAdv Node
|
||||||
|
{
|
||||||
|
get { return _node; }
|
||||||
|
internal set { _node = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeControl _control;
|
||||||
|
public NodeControl Control
|
||||||
|
{
|
||||||
|
get { return _control; }
|
||||||
|
internal set { _control = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point _viewLocation;
|
||||||
|
public Point ViewLocation
|
||||||
|
{
|
||||||
|
get { return _viewLocation; }
|
||||||
|
internal set { _viewLocation = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Keys _modifierKeys;
|
||||||
|
public Keys ModifierKeys
|
||||||
|
{
|
||||||
|
get { return _modifierKeys; }
|
||||||
|
internal set { _modifierKeys = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _handled;
|
||||||
|
public bool Handled
|
||||||
|
{
|
||||||
|
get { return _handled; }
|
||||||
|
set { _handled = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle _controlBounds;
|
||||||
|
public Rectangle ControlBounds
|
||||||
|
{
|
||||||
|
get { return _controlBounds; }
|
||||||
|
internal set { _controlBounds = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeNodeAdvMouseEventArgs(MouseEventArgs args)
|
||||||
|
: base(args.Button, args.Clicks, args.X, args.Y, args.Delta)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/TreePath.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class TreePath
|
||||||
|
{
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
||||||
|
public static readonly TreePath Empty = new TreePath();
|
||||||
|
|
||||||
|
private object[] _path;
|
||||||
|
public object[] FullPath
|
||||||
|
{
|
||||||
|
get { return _path; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public object LastNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_path.Length > 0)
|
||||||
|
return _path[_path.Length - 1];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object FirstNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_path.Length > 0)
|
||||||
|
return _path[0];
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePath()
|
||||||
|
{
|
||||||
|
_path = new object[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePath(object node)
|
||||||
|
{
|
||||||
|
_path = new object[] { node };
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePath(object[] path)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePath(TreePath parent, object node)
|
||||||
|
{
|
||||||
|
_path = new object[parent.FullPath.Length + 1];
|
||||||
|
for (int i = 0; i < _path.Length - 1; i++)
|
||||||
|
_path[i] = parent.FullPath[i];
|
||||||
|
_path[_path.Length - 1] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEmpty()
|
||||||
|
{
|
||||||
|
return (_path.Length == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public class TreePathEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
private TreePath _path;
|
||||||
|
public TreePath Path
|
||||||
|
{
|
||||||
|
get { return _path; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePathEventArgs()
|
||||||
|
{
|
||||||
|
_path = new TreePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreePathEventArgs(TreePath path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
_path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/TreeViewAdv.Designer.cs
generated
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
partial class TreeViewAdv
|
||||||
|
{
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
if (_dragBitmap != null) _dragBitmap.Dispose();
|
||||||
|
if (_dragTimer != null) _dragTimer.Dispose();
|
||||||
|
if (_linePen != null) _linePen.Dispose();
|
||||||
|
if (_markPen != null) _markPen.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Component Designer generated code
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this._vScrollBar = new System.Windows.Forms.VScrollBar();
|
||||||
|
this._hScrollBar = new System.Windows.Forms.HScrollBar();
|
||||||
|
this._errorProvider = new System.Windows.Forms.ErrorProvider(this.components);
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this._errorProvider)).BeginInit();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// _vScrollBar
|
||||||
|
//
|
||||||
|
this._vScrollBar.LargeChange = 1;
|
||||||
|
this._vScrollBar.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this._vScrollBar.Maximum = 0;
|
||||||
|
this._vScrollBar.Name = "_vScrollBar";
|
||||||
|
this._vScrollBar.Size = new System.Drawing.Size(13, 80);
|
||||||
|
this._vScrollBar.TabIndex = 1;
|
||||||
|
this._vScrollBar.ValueChanged += new System.EventHandler(this._vScrollBar_ValueChanged);
|
||||||
|
this._vScrollBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this._vScrollBar_Scroll);
|
||||||
|
//
|
||||||
|
// _hScrollBar
|
||||||
|
//
|
||||||
|
this._hScrollBar.LargeChange = 1;
|
||||||
|
this._hScrollBar.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this._hScrollBar.Maximum = 0;
|
||||||
|
this._hScrollBar.Name = "_hScrollBar";
|
||||||
|
this._hScrollBar.Size = new System.Drawing.Size(80, 13);
|
||||||
|
this._hScrollBar.TabIndex = 2;
|
||||||
|
this._hScrollBar.ValueChanged += new System.EventHandler(this._hScrollBar_ValueChanged);
|
||||||
|
this._hScrollBar.Scroll += new System.Windows.Forms.ScrollEventHandler(this._hScrollBar_Scroll);
|
||||||
|
//
|
||||||
|
// TreeViewAdv
|
||||||
|
//
|
||||||
|
this.BackColor = System.Drawing.SystemColors.Window;
|
||||||
|
this.Controls.Add(this._vScrollBar);
|
||||||
|
this.Controls.Add(this._hScrollBar);
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this._errorProvider)).EndInit();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private VScrollBar _vScrollBar;
|
||||||
|
private HScrollBar _hScrollBar;
|
||||||
|
private ErrorProvider _errorProvider;
|
||||||
|
}
|
||||||
|
}
|
||||||
310
LibreHardwareMonitor-0.9.4/Aga.Controls/Tree/TreeViewAdv.Draw.cs
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public partial class TreeViewAdv
|
||||||
|
{
|
||||||
|
public void AutoSizeColumn(TreeColumn column)
|
||||||
|
{
|
||||||
|
if (!Columns.Contains(column))
|
||||||
|
throw new ArgumentException("column");
|
||||||
|
|
||||||
|
DrawContext context = new DrawContext();
|
||||||
|
context.Graphics = Graphics.FromImage(new Bitmap(1, 1));
|
||||||
|
context.Font = this.Font;
|
||||||
|
int res = 0;
|
||||||
|
for (int row = 0; row < RowCount; row++)
|
||||||
|
{
|
||||||
|
if (row < RowMap.Count)
|
||||||
|
{
|
||||||
|
int w = 0;
|
||||||
|
TreeNodeAdv node = RowMap[row];
|
||||||
|
foreach (NodeControl nc in NodeControls)
|
||||||
|
{
|
||||||
|
if (nc.ParentColumn == column)
|
||||||
|
w += nc.GetActualSize(node, _measureContext).Width;
|
||||||
|
}
|
||||||
|
res = Math.Max(res, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res > 0)
|
||||||
|
column.Width = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreatePens()
|
||||||
|
{
|
||||||
|
CreateLinePen();
|
||||||
|
CreateMarkPen();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateMarkPen()
|
||||||
|
{
|
||||||
|
GraphicsPath path = new GraphicsPath();
|
||||||
|
path.AddLines(new Point[] { new Point(0, 0), new Point(1, 1), new Point(-1, 1), new Point(0, 0) });
|
||||||
|
CustomLineCap cap = new CustomLineCap(null, path);
|
||||||
|
cap.WidthScale = 1.0f;
|
||||||
|
|
||||||
|
_markPen = new Pen(_dragDropMarkColor, _dragDropMarkWidth);
|
||||||
|
_markPen.CustomStartCap = cap;
|
||||||
|
_markPen.CustomEndCap = cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateLinePen()
|
||||||
|
{
|
||||||
|
_linePen = new Pen(_lineColor);
|
||||||
|
_linePen.DashStyle = DashStyle.Dot;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
BeginPerformanceCount();
|
||||||
|
PerformanceAnalyzer.Start("OnPaint");
|
||||||
|
|
||||||
|
DrawContext context = new DrawContext();
|
||||||
|
context.Graphics = e.Graphics;
|
||||||
|
context.Font = this.Font;
|
||||||
|
context.Enabled = Enabled;
|
||||||
|
|
||||||
|
int y = 0;
|
||||||
|
int gridHeight = 0;
|
||||||
|
|
||||||
|
if (UseColumns)
|
||||||
|
{
|
||||||
|
DrawColumnHeaders(e.Graphics);
|
||||||
|
y += ColumnHeaderHeight;
|
||||||
|
if (Columns.Count == 0 || e.ClipRectangle.Height <= y)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstRowY = _rowLayout.GetRowBounds(FirstVisibleRow).Y;
|
||||||
|
y -= firstRowY;
|
||||||
|
|
||||||
|
e.Graphics.ResetTransform();
|
||||||
|
e.Graphics.TranslateTransform(-OffsetX, y);
|
||||||
|
Rectangle displayRect = DisplayRectangle;
|
||||||
|
for (int row = FirstVisibleRow; row < RowCount; row++)
|
||||||
|
{
|
||||||
|
Rectangle rowRect = _rowLayout.GetRowBounds(row);
|
||||||
|
gridHeight += rowRect.Height;
|
||||||
|
if (rowRect.Y + y > displayRect.Bottom)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
DrawRow(e, ref context, row, rowRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((GridLineStyle & GridLineStyle.Vertical) == GridLineStyle.Vertical && UseColumns)
|
||||||
|
DrawVerticalGridLines(e.Graphics, firstRowY);
|
||||||
|
|
||||||
|
if (_dropPosition.Node != null && DragMode && HighlightDropPosition)
|
||||||
|
DrawDropMark(e.Graphics);
|
||||||
|
|
||||||
|
e.Graphics.ResetTransform();
|
||||||
|
DrawScrollBarsBox(e.Graphics);
|
||||||
|
|
||||||
|
if (DragMode && _dragBitmap != null)
|
||||||
|
e.Graphics.DrawImage(_dragBitmap, PointToClient(MousePosition));
|
||||||
|
|
||||||
|
PerformanceAnalyzer.Finish("OnPaint");
|
||||||
|
EndPerformanceCount(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawRow(PaintEventArgs e, ref DrawContext context, int row, Rectangle rowRect)
|
||||||
|
{
|
||||||
|
TreeNodeAdv node = RowMap[row];
|
||||||
|
context.DrawSelection = DrawSelectionMode.None;
|
||||||
|
context.CurrentEditorOwner = CurrentEditorOwner;
|
||||||
|
if (DragMode)
|
||||||
|
{
|
||||||
|
if ((_dropPosition.Node == node) && _dropPosition.Position == NodePosition.Inside && HighlightDropPosition)
|
||||||
|
context.DrawSelection = DrawSelectionMode.Active;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (node.IsSelected && Focused)
|
||||||
|
context.DrawSelection = DrawSelectionMode.Active;
|
||||||
|
else if (node.IsSelected && !Focused && !HideSelection)
|
||||||
|
context.DrawSelection = DrawSelectionMode.Inactive;
|
||||||
|
}
|
||||||
|
context.DrawFocus = Focused && CurrentNode == node;
|
||||||
|
|
||||||
|
OnRowDraw(e, node, context, row, rowRect);
|
||||||
|
|
||||||
|
if ((GridLineStyle & GridLineStyle.Horizontal) == GridLineStyle.Horizontal) {
|
||||||
|
e.Graphics.DrawLine(CustomHorizontalLinePen, 0, rowRect.Bottom, e.Graphics.ClipBounds.Right, rowRect.Bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FullRowSelect)
|
||||||
|
{
|
||||||
|
context.DrawFocus = false;
|
||||||
|
if (context.DrawSelection == DrawSelectionMode.Active || context.DrawSelection == DrawSelectionMode.Inactive)
|
||||||
|
{
|
||||||
|
Rectangle focusRect = new Rectangle(OffsetX, rowRect.Y, ClientRectangle.Width, rowRect.Height);
|
||||||
|
if (context.DrawSelection == DrawSelectionMode.Active)
|
||||||
|
{
|
||||||
|
e.Graphics.FillRectangle(CustomSelectedRowBrush, focusRect);
|
||||||
|
context.DrawSelection = DrawSelectionMode.FullRowSelect;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e.Graphics.FillRectangle(CustomSelectedRowBrush, focusRect);
|
||||||
|
context.DrawSelection = DrawSelectionMode.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShowLines)
|
||||||
|
DrawLines(e.Graphics, node, rowRect);
|
||||||
|
|
||||||
|
DrawNode(node, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawVerticalGridLines(Graphics gr, int y)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
foreach (TreeColumn c in Columns)
|
||||||
|
{
|
||||||
|
if (c.IsVisible)
|
||||||
|
{
|
||||||
|
x += c.Width;
|
||||||
|
gr.DrawLine(SystemPens.InactiveBorder, x - 1, y, x - 1, gr.ClipBounds.Bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawColumnHeaders(Graphics gr)
|
||||||
|
{
|
||||||
|
PerformanceAnalyzer.Start("DrawColumnHeaders");
|
||||||
|
ReorderColumnState reorder = Input as ReorderColumnState;
|
||||||
|
int x = 0;
|
||||||
|
TreeColumn.DrawBackground(gr, new Rectangle(0, 0, ClientRectangle.Width + 2, ColumnHeaderHeight - 1), false, false);
|
||||||
|
gr.TranslateTransform(-OffsetX, 0);
|
||||||
|
foreach (TreeColumn c in Columns)
|
||||||
|
{
|
||||||
|
if (c.IsVisible)
|
||||||
|
{
|
||||||
|
if (x >= OffsetX && x - OffsetX < this.Bounds.Width)// skip invisible columns
|
||||||
|
{
|
||||||
|
Rectangle rect = new Rectangle(x, 0, c.Width, ColumnHeaderHeight - 1);
|
||||||
|
gr.SetClip(rect);
|
||||||
|
bool pressed = ((Input is ClickColumnState || reorder != null) && ((Input as ColumnState).Column == c));
|
||||||
|
c.Draw(gr, rect, Font, pressed, _hotColumn == c);
|
||||||
|
gr.ResetClip();
|
||||||
|
|
||||||
|
if (reorder != null && reorder.DropColumn == c)
|
||||||
|
TreeColumn.DrawDropMark(gr, rect);
|
||||||
|
}
|
||||||
|
x += c.Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reorder != null)
|
||||||
|
{
|
||||||
|
if (reorder.DropColumn == null)
|
||||||
|
TreeColumn.DrawDropMark(gr, new Rectangle(x, 0, 0, ColumnHeaderHeight));
|
||||||
|
gr.DrawImage(reorder.GhostImage, new Point(reorder.Location.X + + reorder.DragOffset, reorder.Location.Y));
|
||||||
|
}
|
||||||
|
PerformanceAnalyzer.Finish("DrawColumnHeaders");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawNode(TreeNodeAdv node, DrawContext context)
|
||||||
|
{
|
||||||
|
foreach (NodeControlInfo item in GetNodeControls(node))
|
||||||
|
{
|
||||||
|
if (item.Bounds.Right >= OffsetX && item.Bounds.X - OffsetX < this.Bounds.Width)// skip invisible nodes
|
||||||
|
{
|
||||||
|
context.Bounds = item.Bounds;
|
||||||
|
context.Graphics.SetClip(context.Bounds);
|
||||||
|
item.Control.Draw(node, context);
|
||||||
|
context.Graphics.ResetClip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawScrollBarsBox(Graphics gr)
|
||||||
|
{
|
||||||
|
Rectangle r1 = DisplayRectangle;
|
||||||
|
Rectangle r2 = ClientRectangle;
|
||||||
|
gr.FillRectangle(SystemBrushes.Control,
|
||||||
|
new Rectangle(r1.Right, r1.Bottom, r2.Width - r1.Width, r2.Height - r1.Height));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawDropMark(Graphics gr)
|
||||||
|
{
|
||||||
|
if (_dropPosition.Position == NodePosition.Inside)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Rectangle rect = GetNodeBounds(_dropPosition.Node);
|
||||||
|
int right = DisplayRectangle.Right - LeftMargin + OffsetX;
|
||||||
|
int y = rect.Y;
|
||||||
|
if (_dropPosition.Position == NodePosition.After)
|
||||||
|
y = rect.Bottom;
|
||||||
|
gr.DrawLine(_markPen, rect.X, y, right, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawLines(Graphics gr, TreeNodeAdv node, Rectangle rowRect)
|
||||||
|
{
|
||||||
|
if (UseColumns && Columns.Count > 0)
|
||||||
|
gr.SetClip(new Rectangle(0, rowRect.Y, Columns[0].Width, rowRect.Bottom));
|
||||||
|
|
||||||
|
TreeNodeAdv curNode = node;
|
||||||
|
while (curNode != _root && curNode != null)
|
||||||
|
{
|
||||||
|
int level = curNode.Level;
|
||||||
|
int scaledIndent = node.Tree.GetScaledSize(_indent, false);
|
||||||
|
int x = (level - 1) * scaledIndent + NodePlusMinus.ImageSize / 2 + LeftMargin;
|
||||||
|
int width = node.Tree.GetScaledSize(NodePlusMinus.Width - NodePlusMinus.ImageSize / 2, false);
|
||||||
|
int y = rowRect.Y;
|
||||||
|
int y2 = y + rowRect.Height;
|
||||||
|
|
||||||
|
if (curNode == node)
|
||||||
|
{
|
||||||
|
int midy = y + rowRect.Height / 2;
|
||||||
|
gr.DrawLine(_linePen, x, midy, x + width, midy);
|
||||||
|
if (curNode.NextNode == null)
|
||||||
|
y2 = y + rowRect.Height / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.Row == 0)
|
||||||
|
y = rowRect.Height / 2;
|
||||||
|
if (curNode.NextNode != null || curNode == node)
|
||||||
|
gr.DrawLine(_linePen, x, y, x, y2);
|
||||||
|
|
||||||
|
curNode = curNode.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
gr.ResetClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Performance
|
||||||
|
|
||||||
|
private double _totalTime;
|
||||||
|
private int _paintCount;
|
||||||
|
|
||||||
|
[Conditional("PERF_TEST")]
|
||||||
|
private void BeginPerformanceCount()
|
||||||
|
{
|
||||||
|
_paintCount++;
|
||||||
|
TimeCounter.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Conditional("PERF_TEST")]
|
||||||
|
private void EndPerformanceCount(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
double time = TimeCounter.Finish();
|
||||||
|
_totalTime += time;
|
||||||
|
string debugText = string.Format("FPS {0:0.0}; Avg. FPS {1:0.0}",
|
||||||
|
1 / time, 1 / (_totalTime / _paintCount));
|
||||||
|
e.Graphics.FillRectangle(Brushes.White, new Rectangle(DisplayRectangle.Width - 150, DisplayRectangle.Height - 20, 150, 20));
|
||||||
|
e.Graphics.DrawString(debugText, Control.DefaultFont, Brushes.Gray,
|
||||||
|
new PointF(DisplayRectangle.Width - 150, DisplayRectangle.Height - 20));
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
partial class TreeViewAdv
|
||||||
|
{
|
||||||
|
private TreeNodeAdv _editingNode;
|
||||||
|
|
||||||
|
public EditableControl CurrentEditorOwner { get; private set; }
|
||||||
|
public Control CurrentEditor { get; private set; }
|
||||||
|
|
||||||
|
public void HideEditor()
|
||||||
|
{
|
||||||
|
if (CurrentEditorOwner != null)
|
||||||
|
CurrentEditorOwner.EndEdit(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void DisplayEditor(Control editor, EditableControl owner)
|
||||||
|
{
|
||||||
|
if (editor == null || owner == null || CurrentNode == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
|
HideEditor(false);
|
||||||
|
|
||||||
|
CurrentEditor = editor;
|
||||||
|
CurrentEditorOwner = owner;
|
||||||
|
_editingNode = CurrentNode;
|
||||||
|
|
||||||
|
editor.Validating += EditorValidating;
|
||||||
|
UpdateEditorBounds();
|
||||||
|
UpdateView();
|
||||||
|
editor.Parent = this;
|
||||||
|
editor.Focus();
|
||||||
|
owner.UpdateEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool HideEditor(bool applyChanges)
|
||||||
|
{
|
||||||
|
if (CurrentEditor != null)
|
||||||
|
{
|
||||||
|
if (applyChanges)
|
||||||
|
{
|
||||||
|
if (!ApplyChanges())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check once more if editor was closed in ApplyChanges
|
||||||
|
if (CurrentEditor != null)
|
||||||
|
{
|
||||||
|
CurrentEditor.Validating -= EditorValidating;
|
||||||
|
CurrentEditorOwner.DoDisposeEditor(CurrentEditor);
|
||||||
|
|
||||||
|
CurrentEditor.Parent = null;
|
||||||
|
CurrentEditor.Dispose();
|
||||||
|
|
||||||
|
CurrentEditor = null;
|
||||||
|
CurrentEditorOwner = null;
|
||||||
|
_editingNode = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ApplyChanges()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CurrentEditorOwner.ApplyChanges(_editingNode, CurrentEditor);
|
||||||
|
_errorProvider.Clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ArgumentException ex)
|
||||||
|
{
|
||||||
|
_errorProvider.SetError(CurrentEditor, ex.Message);
|
||||||
|
/*CurrentEditor.Validating -= EditorValidating;
|
||||||
|
MessageBox.Show(this, ex.Message, "Value is not valid", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
CurrentEditor.Focus();
|
||||||
|
CurrentEditor.Validating += EditorValidating;*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorValidating(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
|
{
|
||||||
|
e.Cancel = !ApplyChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateEditorBounds()
|
||||||
|
{
|
||||||
|
if (CurrentEditor != null)
|
||||||
|
{
|
||||||
|
EditorContext context = new EditorContext();
|
||||||
|
context.Owner = CurrentEditorOwner;
|
||||||
|
context.CurrentNode = CurrentNode;
|
||||||
|
context.Editor = CurrentEditor;
|
||||||
|
context.DrawContext = _measureContext;
|
||||||
|
SetEditorBounds(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetEditorBounds(EditorContext context)
|
||||||
|
{
|
||||||
|
foreach (NodeControlInfo info in GetNodeControls(context.CurrentNode))
|
||||||
|
{
|
||||||
|
if (context.Owner == info.Control && info.Control is EditableControl)
|
||||||
|
{
|
||||||
|
Point p = info.Bounds.Location;
|
||||||
|
p.X += info.Control.LeftMargin;
|
||||||
|
p.X -= OffsetX;
|
||||||
|
p.Y -= (_rowLayout.GetRowBounds(FirstVisibleRow).Y - ColumnHeaderHeight);
|
||||||
|
int width = DisplayRectangle.Width - p.X;
|
||||||
|
if (UseColumns && info.Control.ParentColumn != null && Columns.Contains(info.Control.ParentColumn))
|
||||||
|
{
|
||||||
|
Rectangle rect = GetColumnBounds(info.Control.ParentColumn.Index);
|
||||||
|
width = rect.Right - OffsetX - p.X;
|
||||||
|
}
|
||||||
|
context.Bounds = new Rectangle(p.X, p.Y, width, info.Bounds.Height);
|
||||||
|
((EditableControl)info.Control).SetEditorBounds(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Rectangle GetColumnBounds(int column)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
for (int i = 0; i < Columns.Count; i++)
|
||||||
|
{
|
||||||
|
if (Columns[i].IsVisible)
|
||||||
|
{
|
||||||
|
if (i < column)
|
||||||
|
x += Columns[i].Width;
|
||||||
|
else
|
||||||
|
return new Rectangle(x, 0, Columns[i].Width, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Rectangle.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,558 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public partial class TreeViewAdv
|
||||||
|
{
|
||||||
|
#region Keys
|
||||||
|
|
||||||
|
protected override bool IsInputChar(char charCode)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsInputKey(Keys keyData)
|
||||||
|
{
|
||||||
|
if (((keyData & Keys.Up) == Keys.Up)
|
||||||
|
|| ((keyData & Keys.Down) == Keys.Down)
|
||||||
|
|| ((keyData & Keys.Left) == Keys.Left)
|
||||||
|
|| ((keyData & Keys.Right) == Keys.Right))
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return base.IsInputKey(keyData);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ChangeInput()
|
||||||
|
{
|
||||||
|
if ((ModifierKeys & Keys.Shift) == Keys.Shift)
|
||||||
|
{
|
||||||
|
if (!(Input is InputWithShift))
|
||||||
|
Input = new InputWithShift(this);
|
||||||
|
}
|
||||||
|
else if ((ModifierKeys & Keys.Control) == Keys.Control)
|
||||||
|
{
|
||||||
|
if (!(Input is InputWithControl))
|
||||||
|
Input = new InputWithControl(this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(Input.GetType() == typeof(NormalInputState)))
|
||||||
|
Input = new NormalInputState(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnKeyDown(e);
|
||||||
|
if (!e.Handled)
|
||||||
|
{
|
||||||
|
if (e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey)
|
||||||
|
ChangeInput();
|
||||||
|
Input.KeyDown(e);
|
||||||
|
if (!e.Handled)
|
||||||
|
{
|
||||||
|
foreach (NodeControlInfo item in GetNodeControls(CurrentNode))
|
||||||
|
{
|
||||||
|
item.Control.KeyDown(e);
|
||||||
|
if (e.Handled)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnKeyUp(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnKeyUp(e);
|
||||||
|
if (!e.Handled)
|
||||||
|
{
|
||||||
|
if (e.KeyCode == Keys.ShiftKey || e.KeyCode == Keys.ControlKey)
|
||||||
|
ChangeInput();
|
||||||
|
if (!e.Handled)
|
||||||
|
{
|
||||||
|
foreach (NodeControlInfo item in GetNodeControls(CurrentNode))
|
||||||
|
{
|
||||||
|
item.Control.KeyUp(e);
|
||||||
|
if (e.Handled)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnKeyPress(KeyPressEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnKeyPress(e);
|
||||||
|
if (!e.Handled)
|
||||||
|
_search.Search(e.KeyChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Mouse
|
||||||
|
|
||||||
|
private TreeNodeAdvMouseEventArgs CreateMouseArgs(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
TreeNodeAdvMouseEventArgs args = new TreeNodeAdvMouseEventArgs(e);
|
||||||
|
args.ViewLocation = new Point(e.X + OffsetX,
|
||||||
|
e.Y + _rowLayout.GetRowBounds(FirstVisibleRow).Y - ColumnHeaderHeight);
|
||||||
|
args.ModifierKeys = ModifierKeys;
|
||||||
|
args.Node = GetNodeAt(e.Location);
|
||||||
|
NodeControlInfo info = GetNodeControlInfoAt(args.Node, e.Location);
|
||||||
|
args.ControlBounds = info.Bounds;
|
||||||
|
args.Control = info.Control;
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseWheel(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
_search.EndSearch();
|
||||||
|
if (SystemInformation.MouseWheelScrollLines > 0)
|
||||||
|
{
|
||||||
|
int lines = e.Delta / 120 * SystemInformation.MouseWheelScrollLines;
|
||||||
|
int newValue = _vScrollBar.Value - lines;
|
||||||
|
newValue = Math.Min(_vScrollBar.Maximum - _vScrollBar.LargeChange + 1, newValue);
|
||||||
|
newValue = Math.Min(_vScrollBar.Maximum, newValue);
|
||||||
|
_vScrollBar.Value = Math.Max(_vScrollBar.Minimum, newValue);
|
||||||
|
}
|
||||||
|
base.OnMouseWheel(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseDown(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (CurrentEditorOwner != null)
|
||||||
|
{
|
||||||
|
CurrentEditorOwner.EndEdit(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Focused)
|
||||||
|
Focus();
|
||||||
|
|
||||||
|
_search.EndSearch();
|
||||||
|
if (e.Button == MouseButtons.Left)
|
||||||
|
{
|
||||||
|
TreeColumn c;
|
||||||
|
c = GetColumnDividerAt(e.Location);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
Input = new ResizeColumnState(this, c, e.Location);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c = GetColumnAt(e.Location);
|
||||||
|
if (c != null)
|
||||||
|
{
|
||||||
|
Input = new ClickColumnState(this, c, e.Location);
|
||||||
|
UpdateView();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ChangeInput();
|
||||||
|
TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e);
|
||||||
|
|
||||||
|
if (args.Node != null && args.Control != null)
|
||||||
|
args.Control.MouseDown(args);
|
||||||
|
|
||||||
|
if (!args.Handled)
|
||||||
|
Input.MouseDown(args);
|
||||||
|
|
||||||
|
base.OnMouseDown(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseClick(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
//TODO: Disable when click on plusminus icon
|
||||||
|
TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e);
|
||||||
|
if (args.Node != null)
|
||||||
|
OnNodeMouseClick(args);
|
||||||
|
|
||||||
|
base.OnMouseClick(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseDoubleClick(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e);
|
||||||
|
|
||||||
|
if (args.Node != null && args.Control != null)
|
||||||
|
args.Control.MouseDoubleClick(args);
|
||||||
|
|
||||||
|
if (!args.Handled)
|
||||||
|
{
|
||||||
|
if (args.Node != null)
|
||||||
|
OnNodeMouseDoubleClick(args);
|
||||||
|
else
|
||||||
|
Input.MouseDoubleClick(args);
|
||||||
|
|
||||||
|
if (!args.Handled)
|
||||||
|
{
|
||||||
|
if (args.Node != null && args.Button == MouseButtons.Left)
|
||||||
|
args.Node.IsExpanded = !args.Node.IsExpanded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnMouseDoubleClick(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseUp(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e);
|
||||||
|
if (Input is ResizeColumnState)
|
||||||
|
Input.MouseUp(args);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (args.Node != null && args.Control != null)
|
||||||
|
args.Control.MouseUp(args);
|
||||||
|
if (!args.Handled)
|
||||||
|
Input.MouseUp(args);
|
||||||
|
|
||||||
|
base.OnMouseUp(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseMove(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (Input.MouseMove(e))
|
||||||
|
return;
|
||||||
|
|
||||||
|
base.OnMouseMove(e);
|
||||||
|
SetCursor(e);
|
||||||
|
UpdateToolTip(e);
|
||||||
|
if (ItemDragMode && Dist(e.Location, ItemDragStart) > ItemDragSensivity
|
||||||
|
&& CurrentNode != null && CurrentNode.IsSelected)
|
||||||
|
{
|
||||||
|
ItemDragMode = false;
|
||||||
|
_toolTip.Active = false;
|
||||||
|
OnItemDrag(e.Button, Selection.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnMouseLeave(EventArgs e)
|
||||||
|
{
|
||||||
|
_hotColumn = null;
|
||||||
|
UpdateHeaders();
|
||||||
|
base.OnMouseLeave(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetCursor(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
TreeColumn col;
|
||||||
|
col = GetColumnDividerAt(e.Location);
|
||||||
|
if (col == null)
|
||||||
|
_innerCursor = null;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (col.Width == 0)
|
||||||
|
_innerCursor = ResourceHelper.DVSplitCursor;
|
||||||
|
else
|
||||||
|
_innerCursor = Cursors.VSplit;
|
||||||
|
}
|
||||||
|
|
||||||
|
col = GetColumnAt(e.Location);
|
||||||
|
if (col != _hotColumn)
|
||||||
|
{
|
||||||
|
_hotColumn = col;
|
||||||
|
UpdateHeaders();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TreeColumn GetColumnAt(Point p)
|
||||||
|
{
|
||||||
|
if (p.Y > ColumnHeaderHeight)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int x = -OffsetX;
|
||||||
|
foreach (TreeColumn col in Columns)
|
||||||
|
{
|
||||||
|
if (col.IsVisible)
|
||||||
|
{
|
||||||
|
Rectangle rect = new Rectangle(x, 0, col.Width, ColumnHeaderHeight);
|
||||||
|
x += col.Width;
|
||||||
|
if (rect.Contains(p))
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal int GetColumnX(TreeColumn column)
|
||||||
|
{
|
||||||
|
int x = -OffsetX;
|
||||||
|
foreach (TreeColumn col in Columns)
|
||||||
|
{
|
||||||
|
if (col.IsVisible)
|
||||||
|
{
|
||||||
|
if (column == col)
|
||||||
|
return x;
|
||||||
|
else
|
||||||
|
x += col.Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal TreeColumn GetColumnDividerAt(Point p)
|
||||||
|
{
|
||||||
|
if (p.Y > ColumnHeaderHeight)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int x = -OffsetX;
|
||||||
|
TreeColumn prevCol = null;
|
||||||
|
Rectangle left, right;
|
||||||
|
foreach (TreeColumn col in Columns)
|
||||||
|
{
|
||||||
|
if (col.IsVisible)
|
||||||
|
{
|
||||||
|
if (col.Width > 0)
|
||||||
|
{
|
||||||
|
left = new Rectangle(x, 0, DividerWidth / 2, ColumnHeaderHeight);
|
||||||
|
right = new Rectangle(x + col.Width - (DividerWidth / 2), 0, DividerWidth / 2, ColumnHeaderHeight);
|
||||||
|
if (left.Contains(p) && prevCol != null)
|
||||||
|
return prevCol;
|
||||||
|
else if (right.Contains(p))
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
prevCol = col;
|
||||||
|
x += col.Width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
left = new Rectangle(x, 0, DividerWidth / 2, ColumnHeaderHeight);
|
||||||
|
if (left.Contains(p) && prevCol != null)
|
||||||
|
return prevCol;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeColumn _tooltipColumn;
|
||||||
|
private void UpdateToolTip(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
TreeColumn col = GetColumnAt(e.Location);
|
||||||
|
if (col != null)
|
||||||
|
{
|
||||||
|
if (col != _tooltipColumn)
|
||||||
|
SetTooltip(col.TooltipText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DisplayNodesTooltip(e);
|
||||||
|
_tooltipColumn = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNodeAdv _hotNode;
|
||||||
|
NodeControl _hotControl;
|
||||||
|
private void DisplayNodesTooltip(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (ShowNodeToolTips)
|
||||||
|
{
|
||||||
|
TreeNodeAdvMouseEventArgs args = CreateMouseArgs(e);
|
||||||
|
if (args.Node != null && args.Control != null)
|
||||||
|
{
|
||||||
|
if (args.Node != _hotNode || args.Control != _hotControl)
|
||||||
|
SetTooltip(GetNodeToolTip(args));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_toolTip.SetToolTip(this, null);
|
||||||
|
|
||||||
|
_hotControl = args.Control;
|
||||||
|
_hotNode = args.Node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_toolTip.SetToolTip(this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetTooltip(string text)
|
||||||
|
{
|
||||||
|
if (!String.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
_toolTip.Active = false;
|
||||||
|
_toolTip.SetToolTip(this, text);
|
||||||
|
_toolTip.Active = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_toolTip.SetToolTip(this, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetNodeToolTip(TreeNodeAdvMouseEventArgs args)
|
||||||
|
{
|
||||||
|
string msg = args.Control.GetToolTip(args.Node);
|
||||||
|
|
||||||
|
BaseTextControl btc = args.Control as BaseTextControl;
|
||||||
|
if (btc != null && btc.DisplayHiddenContentInToolTip && String.IsNullOrEmpty(msg))
|
||||||
|
{
|
||||||
|
Size ms = btc.GetActualSize(args.Node, _measureContext);
|
||||||
|
if (ms.Width > args.ControlBounds.Size.Width || ms.Height > args.ControlBounds.Size.Height
|
||||||
|
|| args.ControlBounds.Right - OffsetX > DisplayRectangle.Width)
|
||||||
|
msg = btc.GetLabel(args.Node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(msg) && DefaultToolTipProvider != null)
|
||||||
|
msg = DefaultToolTipProvider.GetToolTip(args.Node, args.Control);
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region DragDrop
|
||||||
|
|
||||||
|
private bool _dragAutoScrollFlag = false;
|
||||||
|
private Bitmap _dragBitmap = null;
|
||||||
|
private System.Threading.Timer _dragTimer;
|
||||||
|
|
||||||
|
private void StartDragTimer()
|
||||||
|
{
|
||||||
|
if (_dragTimer == null)
|
||||||
|
_dragTimer = new System.Threading.Timer(new TimerCallback(DragTimerTick), null, 0, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StopDragTimer()
|
||||||
|
{
|
||||||
|
if (_dragTimer != null)
|
||||||
|
{
|
||||||
|
_dragTimer.Dispose();
|
||||||
|
_dragTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetDropPosition(Point pt)
|
||||||
|
{
|
||||||
|
TreeNodeAdv node = GetNodeAt(pt);
|
||||||
|
OnDropNodeValidating(pt, ref node);
|
||||||
|
_dropPosition.Node = node;
|
||||||
|
if (node != null)
|
||||||
|
{
|
||||||
|
Rectangle first = _rowLayout.GetRowBounds(FirstVisibleRow);
|
||||||
|
Rectangle bounds = _rowLayout.GetRowBounds(node.Row);
|
||||||
|
float pos = (pt.Y + first.Y - ColumnHeaderHeight - bounds.Y) / (float)bounds.Height;
|
||||||
|
if (pos < TopEdgeSensivity)
|
||||||
|
_dropPosition.Position = NodePosition.Before;
|
||||||
|
else if (pos > (1 - BottomEdgeSensivity))
|
||||||
|
_dropPosition.Position = NodePosition.After;
|
||||||
|
else
|
||||||
|
_dropPosition.Position = NodePosition.Inside;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DragTimerTick(object state)
|
||||||
|
{
|
||||||
|
_dragAutoScrollFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DragAutoScroll()
|
||||||
|
{
|
||||||
|
_dragAutoScrollFlag = false;
|
||||||
|
Point pt = PointToClient(MousePosition);
|
||||||
|
if (pt.Y < 20 && _vScrollBar.Value > 0)
|
||||||
|
_vScrollBar.Value--;
|
||||||
|
else if (pt.Y > Height - 20 && _vScrollBar.Value <= _vScrollBar.Maximum - _vScrollBar.LargeChange)
|
||||||
|
_vScrollBar.Value++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DoDragDropSelectedNodes(DragDropEffects allowedEffects)
|
||||||
|
{
|
||||||
|
if (SelectedNodes.Count > 0)
|
||||||
|
{
|
||||||
|
TreeNodeAdv[] nodes = new TreeNodeAdv[SelectedNodes.Count];
|
||||||
|
SelectedNodes.CopyTo(nodes, 0);
|
||||||
|
DoDragDrop(nodes, allowedEffects);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateDragBitmap(IDataObject data)
|
||||||
|
{
|
||||||
|
if (UseColumns || !DisplayDraggingNodes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TreeNodeAdv[] nodes = data.GetData(typeof(TreeNodeAdv[])) as TreeNodeAdv[];
|
||||||
|
if (nodes != null && nodes.Length > 0)
|
||||||
|
{
|
||||||
|
Rectangle rect = DisplayRectangle;
|
||||||
|
Bitmap bitmap = new Bitmap(rect.Width, rect.Height);
|
||||||
|
using (Graphics gr = Graphics.FromImage(bitmap))
|
||||||
|
{
|
||||||
|
gr.Clear(BackColor);
|
||||||
|
DrawContext context = new DrawContext();
|
||||||
|
context.Graphics = gr;
|
||||||
|
context.Font = Font;
|
||||||
|
context.Enabled = true;
|
||||||
|
int y = 0;
|
||||||
|
int maxWidth = 0;
|
||||||
|
foreach (TreeNodeAdv node in nodes)
|
||||||
|
{
|
||||||
|
if (node.Tree == this)
|
||||||
|
{
|
||||||
|
int x = 0;
|
||||||
|
int height = _rowLayout.GetRowBounds(node.Row).Height;
|
||||||
|
foreach (NodeControl c in NodeControls)
|
||||||
|
{
|
||||||
|
Size s = c.GetActualSize(node, context);
|
||||||
|
if (!s.IsEmpty)
|
||||||
|
{
|
||||||
|
int width = s.Width;
|
||||||
|
rect = new Rectangle(x, y, width, height);
|
||||||
|
x += (width + 1);
|
||||||
|
context.Bounds = rect;
|
||||||
|
c.Draw(node, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y += height;
|
||||||
|
maxWidth = Math.Max(maxWidth, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxWidth > 0 && y > 0)
|
||||||
|
{
|
||||||
|
_dragBitmap = new Bitmap(maxWidth, y, PixelFormat.Format32bppArgb);
|
||||||
|
using (Graphics tgr = Graphics.FromImage(_dragBitmap))
|
||||||
|
tgr.DrawImage(bitmap, Point.Empty);
|
||||||
|
BitmapHelper.SetAlphaChanelValue(_dragBitmap, 150);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_dragBitmap = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDragOver(DragEventArgs drgevent)
|
||||||
|
{
|
||||||
|
ItemDragMode = false;
|
||||||
|
Point pt = PointToClient(new Point(drgevent.X, drgevent.Y));
|
||||||
|
if (_dragAutoScrollFlag)
|
||||||
|
DragAutoScroll();
|
||||||
|
SetDropPosition(pt);
|
||||||
|
UpdateView();
|
||||||
|
base.OnDragOver(drgevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDragEnter(DragEventArgs drgevent)
|
||||||
|
{
|
||||||
|
_search.EndSearch();
|
||||||
|
DragMode = true;
|
||||||
|
CreateDragBitmap(drgevent.Data);
|
||||||
|
base.OnDragEnter(drgevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDragLeave(EventArgs e)
|
||||||
|
{
|
||||||
|
DragMode = false;
|
||||||
|
UpdateView();
|
||||||
|
base.OnDragLeave(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDragDrop(DragEventArgs drgevent)
|
||||||
|
{
|
||||||
|
DragMode = false;
|
||||||
|
UpdateView();
|
||||||
|
base.OnDragDrop(drgevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,727 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Design;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
using Aga.Controls.Tree.NodeControls;
|
||||||
|
|
||||||
|
namespace Aga.Controls.Tree
|
||||||
|
{
|
||||||
|
public partial class TreeViewAdv
|
||||||
|
{
|
||||||
|
private Cursor _innerCursor = null;
|
||||||
|
|
||||||
|
public override Cursor Cursor
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_innerCursor != null)
|
||||||
|
return _innerCursor;
|
||||||
|
else
|
||||||
|
return base.Cursor;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.Cursor = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Internal Properties
|
||||||
|
|
||||||
|
private IRowLayout _rowLayout;
|
||||||
|
|
||||||
|
private bool _dragMode;
|
||||||
|
private bool DragMode
|
||||||
|
{
|
||||||
|
get { return _dragMode; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_dragMode = value;
|
||||||
|
if (!value)
|
||||||
|
{
|
||||||
|
StopDragTimer();
|
||||||
|
if (_dragBitmap != null)
|
||||||
|
_dragBitmap.Dispose();
|
||||||
|
_dragBitmap = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
StartDragTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal int ColumnHeaderHeight
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (UseColumns)
|
||||||
|
return _columnHeaderHeight;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// returns all nodes, which parent is expanded
|
||||||
|
/// </summary>
|
||||||
|
private IEnumerable<TreeNodeAdv> VisibleNodes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TreeNodeAdv node = Root;
|
||||||
|
while (node != null)
|
||||||
|
{
|
||||||
|
node = node.NextVisibleNode;
|
||||||
|
if (node != null)
|
||||||
|
yield return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _suspendSelectionEvent;
|
||||||
|
internal bool SuspendSelectionEvent
|
||||||
|
{
|
||||||
|
get { return _suspendSelectionEvent; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _suspendSelectionEvent)
|
||||||
|
{
|
||||||
|
_suspendSelectionEvent = value;
|
||||||
|
if (!_suspendSelectionEvent && _fireSelectionEvent)
|
||||||
|
OnSelectionChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TreeNodeAdv> _rowMap;
|
||||||
|
internal List<TreeNodeAdv> RowMap
|
||||||
|
{
|
||||||
|
get { return _rowMap; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNodeAdv _selectionStart;
|
||||||
|
internal TreeNodeAdv SelectionStart
|
||||||
|
{
|
||||||
|
get { return _selectionStart; }
|
||||||
|
set { _selectionStart = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputState _input;
|
||||||
|
internal InputState Input
|
||||||
|
{
|
||||||
|
get { return _input; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_input = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _itemDragMode;
|
||||||
|
internal bool ItemDragMode
|
||||||
|
{
|
||||||
|
get { return _itemDragMode; }
|
||||||
|
set { _itemDragMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point _itemDragStart;
|
||||||
|
internal Point ItemDragStart
|
||||||
|
{
|
||||||
|
get { return _itemDragStart; }
|
||||||
|
set { _itemDragStart = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of rows fits to the current page
|
||||||
|
/// </summary>
|
||||||
|
internal int CurrentPageSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _rowLayout.CurrentPageSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of all visible nodes (which parent is expanded)
|
||||||
|
/// </summary>
|
||||||
|
internal int RowCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return RowMap.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _contentWidth = 0;
|
||||||
|
private int ContentWidth
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _contentWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _firstVisibleRow;
|
||||||
|
internal int FirstVisibleRow
|
||||||
|
{
|
||||||
|
get { return _firstVisibleRow; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
HideEditor();
|
||||||
|
_firstVisibleRow = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _offsetX;
|
||||||
|
public int OffsetX
|
||||||
|
{
|
||||||
|
get { return _offsetX; }
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
HideEditor();
|
||||||
|
_offsetX = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Rectangle DisplayRectangle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Rectangle r = ClientRectangle;
|
||||||
|
//r.Y += ColumnHeaderHeight;
|
||||||
|
//r.Height -= ColumnHeaderHeight;
|
||||||
|
int w = _vScrollBar.Visible ? _vScrollBar.Width : 0;
|
||||||
|
int h = _hScrollBar.Visible ? _hScrollBar.Height : 0;
|
||||||
|
return new Rectangle(r.X, r.Y, r.Width - w, r.Height - h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TreeNodeAdv> _selection;
|
||||||
|
internal List<TreeNodeAdv> Selection
|
||||||
|
{
|
||||||
|
get { return _selection; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Properties
|
||||||
|
|
||||||
|
#region DesignTime
|
||||||
|
|
||||||
|
private bool _shiftFirstNode;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool ShiftFirstNode
|
||||||
|
{
|
||||||
|
get { return _shiftFirstNode; }
|
||||||
|
set { _shiftFirstNode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _displayDraggingNodes;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool DisplayDraggingNodes
|
||||||
|
{
|
||||||
|
get { return _displayDraggingNodes; }
|
||||||
|
set { _displayDraggingNodes = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _fullRowSelect;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool FullRowSelect
|
||||||
|
{
|
||||||
|
get { return _fullRowSelect; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_fullRowSelect = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _useColumns;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool UseColumns
|
||||||
|
{
|
||||||
|
get { return _useColumns; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_useColumns = value;
|
||||||
|
FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _allowColumnReorder;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool AllowColumnReorder
|
||||||
|
{
|
||||||
|
get { return _allowColumnReorder; }
|
||||||
|
set { _allowColumnReorder = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _showLines = true;
|
||||||
|
[DefaultValue(true), Category("Behavior")]
|
||||||
|
public bool ShowLines
|
||||||
|
{
|
||||||
|
get { return _showLines; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_showLines = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _showPlusMinus = true;
|
||||||
|
[DefaultValue(true), Category("Behavior")]
|
||||||
|
public bool ShowPlusMinus
|
||||||
|
{
|
||||||
|
get { return _showPlusMinus; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_showPlusMinus = value;
|
||||||
|
FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _showNodeToolTips = false;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool ShowNodeToolTips
|
||||||
|
{
|
||||||
|
get { return _showNodeToolTips; }
|
||||||
|
set { _showNodeToolTips = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic"), DefaultValue(true), Category("Behavior"), Obsolete("No longer used")]
|
||||||
|
public bool KeepNodesExpanded
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
set {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ITreeModel _model;
|
||||||
|
/// <Summary>
|
||||||
|
/// The model associated with this <see cref="TreeViewAdv"/>.
|
||||||
|
/// </Summary>
|
||||||
|
/// <seealso cref="ITreeModel"/>
|
||||||
|
/// <seealso cref="TreeModel"/>
|
||||||
|
[Browsable(false)]
|
||||||
|
public ITreeModel Model
|
||||||
|
{
|
||||||
|
get { return _model; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_model != value)
|
||||||
|
{
|
||||||
|
AbortBackgroundExpandingThreads();
|
||||||
|
if (_model != null)
|
||||||
|
UnbindModelEvents();
|
||||||
|
_model = value;
|
||||||
|
CreateNodes();
|
||||||
|
FullUpdate();
|
||||||
|
if (_model != null)
|
||||||
|
BindModelEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Font _font = SystemFonts.MessageBoxFont;
|
||||||
|
/// <summary>
|
||||||
|
/// The font to render <see cref="TreeViewAdv"/> content in.
|
||||||
|
/// </summary>
|
||||||
|
[Category("Appearance"), Description("The font to render TreeViewAdv content in.")]
|
||||||
|
public override Font Font
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (base.Font);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
base.Font = _font;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (value == DefaultFont)
|
||||||
|
base.Font = _font;
|
||||||
|
else
|
||||||
|
base.Font = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override void ResetFont()
|
||||||
|
{
|
||||||
|
Font = null;
|
||||||
|
}
|
||||||
|
private bool ShouldSerializeFont()
|
||||||
|
{
|
||||||
|
return (!Font.Equals(_font));
|
||||||
|
}
|
||||||
|
// End font property
|
||||||
|
|
||||||
|
private BorderStyle _borderStyle = BorderStyle.Fixed3D;
|
||||||
|
[DefaultValue(BorderStyle.Fixed3D), Category("Appearance")]
|
||||||
|
public BorderStyle BorderStyle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this._borderStyle;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_borderStyle != value)
|
||||||
|
{
|
||||||
|
_borderStyle = value;
|
||||||
|
base.UpdateStyles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _autoRowHeight = false;
|
||||||
|
/// <summary>
|
||||||
|
/// Set to true to expand each row's height to fit the text of it's largest column.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(false), Category("Appearance"), Description("Expand each row's height to fit the text of it's largest column.")]
|
||||||
|
public bool AutoRowHeight
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _autoRowHeight;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_autoRowHeight = value;
|
||||||
|
if (value)
|
||||||
|
_rowLayout = new AutoRowHeightLayout(this, RowHeight);
|
||||||
|
else
|
||||||
|
_rowLayout = new FixedRowHeightLayout(this, RowHeight);
|
||||||
|
FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private GridLineStyle _gridLineStyle = GridLineStyle.None;
|
||||||
|
[DefaultValue(GridLineStyle.None), Category("Appearance")]
|
||||||
|
public GridLineStyle GridLineStyle
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _gridLineStyle;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != _gridLineStyle)
|
||||||
|
{
|
||||||
|
_gridLineStyle = value;
|
||||||
|
UpdateView();
|
||||||
|
OnGridLineStyleChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _rowHeight = 16;
|
||||||
|
[DefaultValue(16), Category("Appearance")]
|
||||||
|
public int RowHeight
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _rowHeight;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException("value");
|
||||||
|
|
||||||
|
_rowHeight = value;
|
||||||
|
_rowLayout.PreferredRowHeight = value;
|
||||||
|
FullUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeSelectionMode _selectionMode = TreeSelectionMode.Single;
|
||||||
|
[DefaultValue(TreeSelectionMode.Single), Category("Behavior")]
|
||||||
|
public TreeSelectionMode SelectionMode
|
||||||
|
{
|
||||||
|
get { return _selectionMode; }
|
||||||
|
set { _selectionMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _hideSelection;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool HideSelection
|
||||||
|
{
|
||||||
|
get { return _hideSelection; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_hideSelection = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _topEdgeSensivity = 0.3f;
|
||||||
|
[DefaultValue(0.3f), Category("Behavior")]
|
||||||
|
public float TopEdgeSensivity
|
||||||
|
{
|
||||||
|
get { return _topEdgeSensivity; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value > 1)
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
_topEdgeSensivity = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _bottomEdgeSensivity = 0.3f;
|
||||||
|
[DefaultValue(0.3f), Category("Behavior")]
|
||||||
|
public float BottomEdgeSensivity
|
||||||
|
{
|
||||||
|
get { return _bottomEdgeSensivity; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0 || value > 1)
|
||||||
|
throw new ArgumentOutOfRangeException("value should be from 0 to 1");
|
||||||
|
_bottomEdgeSensivity = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _loadOnDemand;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool LoadOnDemand
|
||||||
|
{
|
||||||
|
get { return _loadOnDemand; }
|
||||||
|
set { _loadOnDemand = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _unloadCollapsedOnReload = false;
|
||||||
|
[DefaultValue(false), Category("Behavior")]
|
||||||
|
public bool UnloadCollapsedOnReload
|
||||||
|
{
|
||||||
|
get { return _unloadCollapsedOnReload; }
|
||||||
|
set { _unloadCollapsedOnReload = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _indent = 19;
|
||||||
|
[DefaultValue(19), Category("Behavior")]
|
||||||
|
public int Indent
|
||||||
|
{
|
||||||
|
get { return _indent; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_indent = value;
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _lineColor = SystemColors.ControlDark;
|
||||||
|
[Category("Behavior")]
|
||||||
|
public Color LineColor
|
||||||
|
{
|
||||||
|
get { return _lineColor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_lineColor = value;
|
||||||
|
CreateLinePen();
|
||||||
|
UpdateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color _dragDropMarkColor = Color.Black;
|
||||||
|
[Category("Behavior")]
|
||||||
|
public Color DragDropMarkColor
|
||||||
|
{
|
||||||
|
get { return _dragDropMarkColor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_dragDropMarkColor = value;
|
||||||
|
CreateMarkPen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float _dragDropMarkWidth = 3.0f;
|
||||||
|
[DefaultValue(3.0f), Category("Behavior")]
|
||||||
|
public float DragDropMarkWidth
|
||||||
|
{
|
||||||
|
get { return _dragDropMarkWidth; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_dragDropMarkWidth = value;
|
||||||
|
CreateMarkPen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _highlightDropPosition = true;
|
||||||
|
[DefaultValue(true), Category("Behavior")]
|
||||||
|
public bool HighlightDropPosition
|
||||||
|
{
|
||||||
|
get { return _highlightDropPosition; }
|
||||||
|
set { _highlightDropPosition = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeColumnCollection _columns;
|
||||||
|
[Category("Behavior"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||||
|
public Collection<TreeColumn> Columns
|
||||||
|
{
|
||||||
|
get { return _columns; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeControlsCollection _controls;
|
||||||
|
[Category("Behavior"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||||
|
[Editor(typeof(NodeControlCollectionEditor), typeof(UITypeEditor))]
|
||||||
|
public Collection<NodeControl> NodeControls
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _controls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _asyncExpanding;
|
||||||
|
/// <summary>
|
||||||
|
/// When set to true, node contents will be read in background thread.
|
||||||
|
/// </summary>
|
||||||
|
[Category("Behavior"), DefaultValue(false), Description("Read children in a background thread when expanding.")]
|
||||||
|
public bool AsyncExpanding
|
||||||
|
{
|
||||||
|
get { return _asyncExpanding; }
|
||||||
|
set { _asyncExpanding = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region RunTime
|
||||||
|
|
||||||
|
private IToolTipProvider _defaultToolTipProvider = null;
|
||||||
|
[Browsable(false)]
|
||||||
|
public IToolTipProvider DefaultToolTipProvider
|
||||||
|
{
|
||||||
|
get { return _defaultToolTipProvider; }
|
||||||
|
set { _defaultToolTipProvider = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public IEnumerable<TreeNodeAdv> AllNodes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_root.Nodes.Count > 0)
|
||||||
|
{
|
||||||
|
TreeNodeAdv node = _root.Nodes[0];
|
||||||
|
while (node != null)
|
||||||
|
{
|
||||||
|
yield return node;
|
||||||
|
if (node.Nodes.Count > 0)
|
||||||
|
node = node.Nodes[0];
|
||||||
|
else if (node.NextNode != null)
|
||||||
|
node = node.NextNode;
|
||||||
|
else
|
||||||
|
node = node.BottomNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DropPosition _dropPosition;
|
||||||
|
[Browsable(false)]
|
||||||
|
public DropPosition DropPosition
|
||||||
|
{
|
||||||
|
get { return _dropPosition; }
|
||||||
|
set { _dropPosition = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNodeAdv _root;
|
||||||
|
[Browsable(false)]
|
||||||
|
public TreeNodeAdv Root
|
||||||
|
{
|
||||||
|
get { return _root; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReadOnlyCollection<TreeNodeAdv> _readonlySelection;
|
||||||
|
[Browsable(false)]
|
||||||
|
public ReadOnlyCollection<TreeNodeAdv> SelectedNodes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _readonlySelection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public TreeNodeAdv SelectedNode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Selection.Count > 0)
|
||||||
|
{
|
||||||
|
if (CurrentNode != null && CurrentNode.IsSelected)
|
||||||
|
return CurrentNode;
|
||||||
|
else
|
||||||
|
return Selection[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SelectedNode == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BeginUpdate();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
ClearSelectionInternal();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!IsMyNode(value))
|
||||||
|
throw new ArgumentException();
|
||||||
|
|
||||||
|
ClearSelectionInternal();
|
||||||
|
value.IsSelected = true;
|
||||||
|
CurrentNode = value;
|
||||||
|
EnsureVisible(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
EndUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TreeNodeAdv _currentNode;
|
||||||
|
[Browsable(false)]
|
||||||
|
public TreeNodeAdv CurrentNode
|
||||||
|
{
|
||||||
|
get { return _currentNode; }
|
||||||
|
internal set { _currentNode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Browsable(false)]
|
||||||
|
public int ItemCount
|
||||||
|
{
|
||||||
|
get { return RowMap.Count; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates the distance the content is scrolled to the left
|
||||||
|
/// </summary>
|
||||||
|
[Browsable(false)]
|
||||||
|
public int HorizontalScrollPosition
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_hScrollBar.Visible)
|
||||||
|
return _hScrollBar.Value;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||