using Microsoft.UI.Xaml.Automation; using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Shapes; using XFEEDToolBox.Core.Galaxy; using Windows.UI; using System.Windows.Input; namespace XFEEDToolBox.Controls; /// Shared view/filter controls for both galaxy map entry points. public sealed partial class GalaxyFilterPanel:UserControl { public static readonly DependencyProperty FilterProperty=DependencyProperty.Register(nameof(Filter),typeof(GalaxyMapFilter),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty SystemsProperty=DependencyProperty.Register(nameof(Systems),typeof(IReadOnlyList),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty ShipJumpRangeProperty=DependencyProperty.Register(nameof(ShipJumpRange),typeof(double),typeof(GalaxyFilterPanel),new PropertyMetadata(0d,Changed)); public static readonly DependencyProperty InformationStatusProperty=DependencyProperty.Register(nameof(InformationStatus),typeof(string),typeof(GalaxyFilterPanel),new PropertyMetadata("",Changed)); public static readonly DependencyProperty ImportSettingsCommandProperty=DependencyProperty.Register(nameof(ImportSettingsCommand),typeof(ICommand),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty OriginalSettingsStatusProperty=DependencyProperty.Register(nameof(OriginalSettingsStatus),typeof(string),typeof(GalaxyFilterPanel),new PropertyMetadata("",Changed)); public static readonly DependencyProperty OriginalSettingsDetailsProperty=DependencyProperty.Register(nameof(OriginalSettingsDetails),typeof(string),typeof(GalaxyFilterPanel),new PropertyMetadata("",Changed)); public static readonly DependencyProperty OriginalOptionsProperty=DependencyProperty.Register(nameof(OriginalOptions),typeof(IReadOnlyDictionary),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty QueryChoicesProperty=DependencyProperty.Register(nameof(QueryChoices),typeof(IReadOnlyList),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty HistoricalTradeChoicesProperty=DependencyProperty.Register(nameof(HistoricalTradeChoices),typeof(IReadOnlyList),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty HistoricalTradeStatusProperty=DependencyProperty.Register(nameof(HistoricalTradeStatus),typeof(string),typeof(GalaxyFilterPanel),new PropertyMetadata("",Changed)); public static readonly DependencyProperty ThargoidCountsProperty=DependencyProperty.Register(nameof(ThargoidCounts),typeof(IReadOnlyList),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty ThargoidSignalsProperty=DependencyProperty.Register(nameof(ThargoidSignals),typeof(IReadOnlyList),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty ThargoidRecommendationsProperty=DependencyProperty.Register(nameof(ThargoidRecommendations),typeof(IReadOnlyList),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty ThargoidStatusProperty=DependencyProperty.Register(nameof(ThargoidStatus),typeof(string),typeof(GalaxyFilterPanel),new PropertyMetadata("",Changed)); public static readonly DependencyProperty SelectThargoidTargetCommandProperty=DependencyProperty.Register(nameof(SelectThargoidTargetCommand),typeof(ICommand),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty LocatePowerHeadquartersCommandProperty=DependencyProperty.Register(nameof(LocatePowerHeadquartersCommand),typeof(ICommand),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty CommunityGoalTargetsProperty=DependencyProperty.Register(nameof(CommunityGoalTargets),typeof(IReadOnlyList),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty CommunityGoalStatusProperty=DependencyProperty.Register(nameof(CommunityGoalStatus),typeof(string),typeof(GalaxyFilterPanel),new PropertyMetadata("",Changed)); public static readonly DependencyProperty SelectCommunityGoalCommandProperty=DependencyProperty.Register(nameof(SelectCommunityGoalCommand),typeof(ICommand),typeof(GalaxyFilterPanel),new PropertyMetadata(null,Changed)); public GalaxyMapFilter Filter {get=>(GalaxyMapFilter?)GetValue(FilterProperty)??GalaxyMapFilter.Default;set=>SetValue(FilterProperty,value);} public IReadOnlyList Systems {get=>(IReadOnlyList?)GetValue(SystemsProperty)??[];set=>SetValue(SystemsProperty,value);} public double ShipJumpRange {get=>(double)GetValue(ShipJumpRangeProperty);set=>SetValue(ShipJumpRangeProperty,value);} public string InformationStatus {get=>(string)GetValue(InformationStatusProperty);set=>SetValue(InformationStatusProperty,value);} public ICommand? ImportSettingsCommand {get=>(ICommand?)GetValue(ImportSettingsCommandProperty);set=>SetValue(ImportSettingsCommandProperty,value);} public string OriginalSettingsStatus {get=>(string)GetValue(OriginalSettingsStatusProperty);set=>SetValue(OriginalSettingsStatusProperty,value);} public string OriginalSettingsDetails {get=>(string)GetValue(OriginalSettingsDetailsProperty);set=>SetValue(OriginalSettingsDetailsProperty,value);} public IReadOnlyDictionary? OriginalOptions {get=>(IReadOnlyDictionary?)GetValue(OriginalOptionsProperty);set=>SetValue(OriginalOptionsProperty,value);} public IReadOnlyList? QueryChoices {get=>(IReadOnlyList?)GetValue(QueryChoicesProperty);set=>SetValue(QueryChoicesProperty,value);} public IReadOnlyList HistoricalTradeChoices {get=>(IReadOnlyList?)GetValue(HistoricalTradeChoicesProperty)??[];set=>SetValue(HistoricalTradeChoicesProperty,value);} public string HistoricalTradeStatus {get=>(string)GetValue(HistoricalTradeStatusProperty);set=>SetValue(HistoricalTradeStatusProperty,value);} public IReadOnlyList ThargoidCounts {get=>(IReadOnlyList?)GetValue(ThargoidCountsProperty)??[];set=>SetValue(ThargoidCountsProperty,value);} public IReadOnlyList ThargoidSignals {get=>(IReadOnlyList?)GetValue(ThargoidSignalsProperty)??[];set=>SetValue(ThargoidSignalsProperty,value);} public IReadOnlyList ThargoidRecommendations {get=>(IReadOnlyList?)GetValue(ThargoidRecommendationsProperty)??[];set=>SetValue(ThargoidRecommendationsProperty,value);} public string ThargoidStatus {get=>(string)GetValue(ThargoidStatusProperty);set=>SetValue(ThargoidStatusProperty,value);} public ICommand? SelectThargoidTargetCommand {get=>(ICommand?)GetValue(SelectThargoidTargetCommandProperty);set=>SetValue(SelectThargoidTargetCommandProperty,value);} public ICommand? LocatePowerHeadquartersCommand {get=>(ICommand?)GetValue(LocatePowerHeadquartersCommandProperty);set=>SetValue(LocatePowerHeadquartersCommandProperty,value);} public IReadOnlyList CommunityGoalTargets {get=>(IReadOnlyList?)GetValue(CommunityGoalTargetsProperty)??[];set=>SetValue(CommunityGoalTargetsProperty,value);} public string CommunityGoalStatus {get=>(string)GetValue(CommunityGoalStatusProperty);set=>SetValue(CommunityGoalStatusProperty,value);} public ICommand? SelectCommunityGoalCommand {get=>(ICommand?)GetValue(SelectCommunityGoalCommandProperty);set=>SetValue(SelectCommunityGoalCommandProperty,value);} private bool updating; private readonly ComboBox mode=new(){Header="视图模式",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly ComboBox category=new(){Header="星系筛选",HorizontalAlignment=HorizontalAlignment.Stretch,DisplayMemberPath="Label",ItemsSource=GalaxyFilterDefinitions.All}; private readonly ComboBox size=new(){Header="恒星大小",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly ComboBox commodityDirection=new(){Header="商品流向",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly ComboBox powerplayView=new(){Header="势力博弈视图",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly ComboBox activityPower=new(){Header="活动势力范围",PlaceholderText="选择实际势力或全部势力",DisplayMemberPath="Label",HorizontalAlignment=HorizontalAlignment.Stretch}; private string activityChoicesSignature=""; private IReadOnlyList activityChoices=[]; private readonly ComboBox activityType=new(){Header="活动类型",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly CheckBox useMinimumActivity=new(){Content="限制最低近期活动强度"}; private readonly CheckBox territoryActivityEnabled=new(){Content="启用领土活动显示与条件"}; private readonly Slider minimumActivity=new(){Minimum=0,Maximum=1,StepFrequency=.01,TickFrequency=.25,Header="最低近期活动强度",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly StackPanel activityControls=new(){Spacing=5}; private readonly TextBlock activityNote=new(){Text="领土附加条件:仅启用最低强度时按所选势力/活动的原近期计数过滤;计数0有效,缺缓存保持未知。",FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly Button powerHeadquarters=new(){Content="定位所选势力总部",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly Expander thargoidPanel=new(){Header="原游戏信号与推荐星系",HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch,IsExpanded=true}; private readonly StackPanel thargoidCounts=new(){Spacing=3},thargoidSignals=new(){Spacing=5},thargoidRecommendations=new(){Spacing=5}; private readonly TextBlock thargoidStatus=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private IReadOnlyList? renderedThargoidCounts; private IReadOnlyList? renderedThargoidSignals,renderedThargoidRecommendations; private ICommand? renderedThargoidCommand; private readonly StackPanel communityGoalTargets=new(){Spacing=5}; private readonly TextBlock communityGoalStatus=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private IReadOnlyList? renderedCommunityGoals; private ICommand? renderedCommunityGoalCommand; private readonly StackPanel choices=new(){Spacing=0}; private readonly StackPanel commodityGroups=new(){Spacing=5}; private readonly Dictionary commodityLeaves=new(StringComparer.Ordinal); private readonly Dictionary commodityParents=new(StringComparer.Ordinal); private readonly Dictionary commodityExpanded=new(StringComparer.Ordinal); private string commodityTreeSignature=""; private IReadOnlyList currentCommodityGroups=[]; private readonly StackPanel selectionActions=new(){Orientation=Orientation.Horizontal,Spacing=8}; private readonly Expander powerStates=new(){Header="领土状态(与所选势力同时满足)",HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch}; private readonly Dictionary powerStateChecks=new(StringComparer.Ordinal); private readonly TextBox choiceSearch=new(){PlaceholderText="查找筛选值(中文或原名)"}; private readonly TextBlock coverage=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly StackPanel populationLegend=new(){Spacing=3}; private readonly TextBlock populationLegendText=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly TextBlock note=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly TextBlock information=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly CheckBox unknown=new(){Content="显示未知数据的星系"}; private readonly CheckBox grid=new(){Content="星图网格"},gridStalks=new(){Content="星系到网格的投影线(工具选项)"},labels=new(){Content="恒星名称"},links=new(){Content="显示跳跃连接线"},markers=new(){Content="地点与工程师标记"},route=new(){Content="导航标记与航线"},background=new(){Content="银河与星云背景"}; private readonly CheckBox reverseMouseCrane=new(){Content="反转鼠标升降(工具选项)"}; private readonly CheckBox regionNames=new(){Content="原游戏区域名称"},nebulaNames=new(){Content="星云名称"},constellations=new(){Content="星座连线"},galacticZones=new(){Content="银河扇区平面"},galacticZoneNames=new(){Content="银河扇区名称"}; private readonly CheckBox historicalTrade=new(){Content="显示缓存历史贸易流(非实时)"}; private readonly ComboBox historicalTradeSource=new(){Header="历史流量来源",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly TextBox historicalTradeSearch=new(){PlaceholderText="查找缓存中的商品"}; private readonly TextBlock historicalTradeStatus=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly StackPanel historicalTradeCommodities=new(){Spacing=0}; private readonly Dictionary historicalCommodityChecks=new(StringComparer.Ordinal); private string historicalCommoditySignature=""; private readonly NumberBox range=new(){Header="跳跃连接范围 / ly",Minimum=1,Maximum=1000,SmallChange=1,SpinButtonPlacementMode=NumberBoxSpinButtonPlacementMode.Compact}; private readonly NumberBox populationMin=new(){Header="人口下限(人)",Minimum=0,Maximum=9_000_000_000_000_000}; private readonly NumberBox populationMax=new(){Header="人口满值(人)",Minimum=0,Maximum=9_000_000_000_000_000}; private readonly Button shipRange=new(){Content="采用当前飞船最大跳距",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly Button scoop=new(){Content="仅可吸油 O B A F G K M"}; private readonly Button importSettings=new(){Content="读取游戏星图配置",HorizontalAlignment=HorizontalAlignment.Stretch}; private readonly TextBlock importStatus=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly StackPanel originalOptions=new(){Spacing=5}; private readonly TextBlock importDetails=new(){FontSize=11,TextWrapping=TextWrapping.Wrap}; private readonly CheckBox originalRouteFilter=new(){Content="将筛选应用于路线(游戏保存值)",IsEnabled=false,IsThreeState=true}; private IReadOnlyDictionary? renderedOriginalOptions; private readonly Dictionary choiceRows=new(StringComparer.Ordinal); private string renderedChoices=""; private IReadOnlyList? countedSystems; private GalaxyFilterCategory countedCategory=(GalaxyFilterCategory)(-1); private bool countedOriginalState; private GalaxyCommodityDirection countedCommodityDirection; private readonly Dictionary choiceCounts=new(StringComparer.Ordinal); public GalaxyFilterPanel() { InstallStaticCheckBoxTemplate(); Width=300;HorizontalContentAlignment=HorizontalAlignment.Stretch; var muted=(Brush)Application.Current.Resources["MutedBrush"];coverage.Foreground=note.Foreground=information.Foreground=muted; constellations.Content="原游戏星座连线"; ToolTipService.SetToolTip(constellations,"原资源16组、206条实际连线;整组全部端点均真实已载入且通过当前查询才绘制完整组,缺任一端点整组等待。"); mode.Items.Add(new ComboBoxItem{Content="写实模式",Tag=GalaxyMapMode.Realistic});mode.Items.Add(new ComboBoxItem{Content="地图模式",Tag=GalaxyMapMode.Map}); foreach(var (name,value) in new[]{("势力博弈",GalaxyMapMode.Powerplay),("Thargoid 战争模式",GalaxyMapMode.ThargoidWar),("星系殖民模式",GalaxyMapMode.Colonisation)}) {var item=new ComboBoxItem{Content=name,Tag=value};mode.Items.Add(item);} var root=new StackPanel{Spacing=8};root.Children.Add(new TextBlock{Text="银河系星图 · 视图",FontSize=18,FontWeight=Microsoft.UI.Text.FontWeights.SemiBold}); AutomationProperties.SetName(importSettings,"读取游戏星图配置");importStatus.Foreground=muted; // Original3A3D910 publishes exactly these three radio UIDs/labels. // Saved mode3 is accepted by the predicate but displays the first item. commodityDirection.Items.Add(new ComboBoxItem{Content="进口/出口价格",Tag=GalaxyCommodityDirection.Both});commodityDirection.Items.Add(new ComboBoxItem{Content="进口价格",Tag=GalaxyCommodityDirection.Imports});commodityDirection.Items.Add(new ComboBoxItem{Content="出口价格",Tag=GalaxyCommodityDirection.Exports}); powerplayView.Items.Add(new ComboBoxItem{Content="领土:势力与状态",Tag=GalaxyPowerplayView.Territory});powerplayView.Items.Add(new ComboBoxItem{Content="活动:原范围与星系条件",Tag=GalaxyPowerplayView.Activities}); foreach(var entry in new[]{("暗中破坏",GalaxyPowerActivity.Undermining),("巩固中",GalaxyPowerActivity.Reinforcing),("正在获取",GalaxyPowerActivity.Acquiring),("抵抗破坏",GalaxyPowerActivity.BeingUndermined),("总计",GalaxyPowerActivity.Total)})activityType.Items.Add(new ComboBoxItem{Content=entry.Item1,Tag=entry.Item2}); activityControls.Children.Add(territoryActivityEnabled);activityControls.Children.Add(activityPower);activityControls.Children.Add(activityType);activityControls.Children.Add(useMinimumActivity);activityControls.Children.Add(minimumActivity); activityNote.Foreground=muted;activityControls.Children.Add(activityNote);savedActivityPowerStatus.Foreground=muted;activityControls.Children.Add(savedActivityPowerStatus); root.Children.Add(mode);root.Children.Add(powerplayView);root.Children.Add(category);root.Children.Add(commodityDirection);root.Children.Add(activityControls);root.Children.Add(powerHeadquarters);root.Children.Add(coverage); AutomationProperties.SetName(powerHeadquarters,"定位所选势力总部");ToolTipService.SetToolTip(powerHeadquarters,"选择一个实际势力,读取其原定义中的总部地址并定位;全部势力或未知总部时不可用。"); var thargoidContent=new StackPanel{Spacing=7};thargoidContent.Children.Add(thargoidStatus);thargoidContent.Children.Add(thargoidCounts); thargoidContent.Children.Add(new TextBlock{Text="原信号",FontWeight=Microsoft.UI.Text.FontWeights.SemiBold});thargoidContent.Children.Add(new ScrollViewer{Content=thargoidSignals,MaxHeight=220,VerticalScrollBarVisibility=ScrollBarVisibility.Auto}); thargoidContent.Children.Add(new TextBlock{Text="原推荐星系(每组至多5项)",FontWeight=Microsoft.UI.Text.FontWeights.SemiBold});thargoidContent.Children.Add(new ScrollViewer{Content=thargoidRecommendations,MaxHeight=300,VerticalScrollBarVisibility=ScrollBarVisibility.Auto}); thargoidContent.Children.Add(new TextBlock{Text="点击按真实地址解析并定位。仅显示原游戏已有缓存,不发起原网络更新;列表长度不代替战争状态总数。",FontSize=11,TextWrapping=TextWrapping.Wrap,Foreground=muted}); thargoidPanel.Content=thargoidContent;root.Children.Add(thargoidPanel); var populationRamp=new LinearGradientBrush{StartPoint=new(0,.5),EndPoint=new(1,.5)}; var low=GalaxyMapFilter.PopulationLowColour;var high=GalaxyMapFilter.PopulationHighColour; populationRamp.GradientStops.Add(new GradientStop{Offset=0,Color=Color.FromArgb(255,low.R,low.G,low.B)});populationRamp.GradientStops.Add(new GradientStop{Offset=1,Color=Color.FromArgb(255,high.R,high.G,high.B)}); populationLegend.Children.Add(new Rectangle{Height=6,Fill=populationRamp,HorizontalAlignment=HorizontalAlignment.Stretch});populationLegend.Children.Add(populationLegendText);root.Children.Add(populationLegend); var all=new Button{Content="全选",FontSize=12};var none=new Button{Content="清除",FontSize=12}; scoop.Content="仅可吸油";scoop.FontSize=12;ToolTipService.SetToolTip(scoop,"仅显示可吸油的 O、B、A、F、G、K、M 型恒星"); selectionActions.Children.Add(all);selectionActions.Children.Add(none);selectionActions.Children.Add(scoop);root.Children.Add(selectionActions); root.Children.Add(choiceSearch);root.Children.Add(new ScrollViewer{Content=choices,MaxHeight=238,VerticalScrollBarVisibility=ScrollBarVisibility.Auto,HorizontalScrollBarVisibility=ScrollBarVisibility.Disabled});root.Children.Add(unknown); root.Children.Add(commodityGroups); var powerStateContent=new StackPanel{Spacing=2};var stateAll=new Button{Content="全部状态",HorizontalAlignment=HorizontalAlignment.Stretch};powerStateContent.Children.Add(stateAll);stateAll.Click+=(_,_)=>Filter=Filter with{TerritoryStateMask=null,PowerStateValues=null}; foreach(var state in GalaxyFilterDefinitions.All.First(d=>d.Category==GalaxyFilterCategory.PowerState).Choices) { var check=new CheckBox{Content=state.Label,IsThreeState=true};powerStateChecks[state.Key]=check; void SelectState(object sender,RoutedEventArgs e) {if(updating)return;Filter=Filter with{TerritoryStateMask=GalaxyOriginalPowerFilters.SetStateGroup(Filter.TerritoryStateMask,state.Key,check.IsChecked==true),PowerStateValues=null};} check.Checked+=SelectState;check.Unchecked+=SelectState;check.Indeterminate+=SelectState;powerStateContent.Children.Add(check); } powerStates.Content=powerStateContent;root.Children.Add(powerStates); var dataNotes=new StackPanel{Spacing=6};dataNotes.Children.Add(note);dataNotes.Children.Add(information);dataNotes.Children.Add(new TextBlock{Text="移动或缩放后按当前视野重新查询;未匹配星系隐藏。",FontSize=11,TextWrapping=TextWrapping.Wrap,Foreground=muted}); root.Children.Add(new Expander{Header="资料与覆盖说明",Content=dataNotes,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch}); InitializeSizeOptions(); var display=new StackPanel{Spacing=2};display.Children.Add(size);display.Children.Add(populationMin);display.Children.Add(populationMax);foreach(var toggle in new[]{grid,gridStalks,labels,regionNames,nebulaNames,constellations,galacticZones,galacticZoneNames,links,markers,route,background,reverseMouseCrane})display.Children.Add(toggle);display.Children.Add(range);display.Children.Add(shipRange); display.Children.Add(new TextBlock{Text="名称、星座和扇区图层独立叠加;不会把区域或星云当作恒星筛选。各图层仅绘制已核验的原资源。",FontSize=11,TextWrapping=TextWrapping.Wrap,Foreground=muted}); display.Children.Add(new TextBlock{Text="连线以选中或当前星系为起点,受实际光年距离限制。范围为显示参数,不等于已规划航路。",FontSize=11,TextWrapping=TextWrapping.Wrap,Foreground=muted}); root.Children.Add(new Expander{Header="显示控制",Content=display,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch}); root.Children.Add(BuildCurrentTradeControls()); foreach(var entry in new[]{("全部缓存流量",GalaxyTradeFlowSource.All),("玩家缓存流量",GalaxyTradeFlowSource.Players),("NPC 缓存流量",GalaxyTradeFlowSource.Npc)})historicalTradeSource.Items.Add(new ComboBoxItem{Content=entry.Item1,Tag=entry.Item2}); var history=new StackPanel{Spacing=5};history.Children.Add(historicalTrade);history.Children.Add(historicalTradeSource);history.Children.Add(historicalTradeSearch); var historyAll=new Button{Content="全部商品"};var historyNone=new Button{Content="清除商品"};var historyActions=new StackPanel{Orientation=Orientation.Horizontal,Spacing=7};historyActions.Children.Add(historyAll);historyActions.Children.Add(historyNone);history.Children.Add(historyActions); history.Children.Add(new ScrollViewer{Content=historicalTradeCommodities,MaxHeight=180,VerticalScrollBarVisibility=ScrollBarVisibility.Auto});history.Children.Add(historicalTradeStatus); history.Children.Add(new TextBlock{Text="按原贸易流13类目录分组,仅列缓存实际商品;原目录以外的商品分类保持未知。父类选择作用于整类,查找仅改变列表。",FontSize=11,TextWrapping=TextWrapping.Wrap,Foreground=muted}); history.Children.Add(new TextBlock{Text="来自当前账号原TRD缓存的带时间贸易记录;不会代替游戏实时有效期。只绘制真实地址和坐标已确认的端点。",FontSize=11,TextWrapping=TextWrapping.Wrap,Foreground=muted}); root.Children.Add(new Expander{Header="缓存历史贸易流",Content=history,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch}); historicalTrade.Checked+=(_,_)=>{if(!updating)Filter=Filter with{ShowHistoricalTradeFlows=true};};historicalTrade.Unchecked+=(_,_)=>{if(!updating)Filter=Filter with{ShowHistoricalTradeFlows=false};}; historicalTradeSource.SelectionChanged+=(_,_)=>{if(!updating&&historicalTradeSource.SelectedItem is ComboBoxItem{Tag:GalaxyTradeFlowSource source})Filter=Filter with{HistoricalTradeSource=source};}; historyAll.Click+=(_,_)=>Filter=Filter with{HistoricalTradeCommodities=null};historyNone.Click+=(_,_)=>Filter=Filter with{HistoricalTradeCommodities=new HashSet()};historicalTradeSearch.TextChanged+=(_,_)=>Refresh(); root.Children.Add(importSettings);root.Children.Add(importStatus); root.Children.Add(BuildFleetControls()); root.Children.Add(BuildMissionControls()); var layers=new StackPanel{Spacing=3};layers.Children.Add(new TextBlock{Text="选择标记后查询当前视野;资料说明会列出实际来源与待确认的覆盖。",FontSize=11,Foreground=muted,TextWrapping=TextWrapping.Wrap}); foreach(var entry in GalaxyFilterDefinitions.All.First(d=>d.Category==GalaxyFilterCategory.Markers).Choices) { var button=new Button{Content=entry.Label,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Left}; AutomationProperties.SetName(button,"查询"+entry.Label);button.Click+=(_,_)=>Filter=Filter.WithCategory(GalaxyFilterCategory.Markers) with{Values=new HashSet{entry.Key},IncludeUnknown=false};layers.Children.Add(button); } root.Children.Add(new Expander{Header="原游戏标记查询",Content=new ScrollViewer{Content=layers,MaxHeight=260,VerticalScrollBarVisibility=ScrollBarVisibility.Auto},HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch}); var goals=new StackPanel{Spacing=6};goals.Children.Add(communityGoalStatus);goals.Children.Add(new ScrollViewer{Content=communityGoalTargets,MaxHeight=250,VerticalScrollBarVisibility=ScrollBarVisibility.Auto}); root.Children.Add(new Expander{Header="社区活动 · 原发布缓存",Content=goals,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch}); ToolTipService.SetToolTip(originalRouteFilter,"显示原游戏保存的此类别开关。恒星类别的路线设置可在航行偏好中更改,长按目标规划时应用。");root.Children.Add(originalRouteFilter); var originalContent=new StackPanel{Spacing=7};originalContent.Children.Add(importDetails);originalContent.Children.Add(originalOptions); root.Children.Add(new Expander{Header="原游戏配置值与导入说明(只读)",Content=new ScrollViewer{Content=originalContent,MaxHeight=220,HorizontalScrollBarVisibility=ScrollBarVisibility.Disabled,VerticalScrollBarVisibility=ScrollBarVisibility.Auto},HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch}); root.Children.Add(new TextBlock{Text="筛选即时作用于本工具星图;游戏规划的航路使用游戏内筛选设置。",Foreground=muted,FontSize=11,TextWrapping=TextWrapping.Wrap}); var reset=new Button{Content="恢复默认视图",HorizontalAlignment=HorizontalAlignment.Stretch};root.Children.Add(reset);Content=root; mode.SelectionChanged+=(_,_)=>{if(!updating&&mode.SelectedItem is ComboBoxItem{Tag:GalaxyMapMode selected})Filter=selected switch{GalaxyMapMode.Powerplay=>Filter.WithCategory(GalaxyFilterCategory.Power) with{Mode=selected,Values=null,PowerStateValues=null},GalaxyMapMode.ThargoidWar=>Filter.WithCategory(GalaxyFilterCategory.ThargoidWar) with{Mode=selected},GalaxyMapMode.Colonisation=>Filter.WithCategory(GalaxyFilterCategory.Colonisation) with{Mode=selected},_=>Filter with{Mode=selected}};}; category.SelectionChanged+=(_,_)=>{if(!updating&&category.SelectedItem is GalaxyFilterDefinition selected)Filter=selected.Category==GalaxyFilterCategory.PowerActivityEligibility?Filter.WithCategory(selected.Category) with{Mode=GalaxyMapMode.Powerplay,PowerplayView=GalaxyPowerplayView.Territory}:Filter.WithCategory(selected.Category);}; powerplayView.SelectionChanged+=(_,_)=>{if(!updating&&powerplayView.SelectedItem is ComboBoxItem{Tag:GalaxyPowerplayView selected})Filter=Filter.WithCategory(GalaxyFilterCategory.Power) with{Mode=GalaxyMapMode.Powerplay,PowerplayView=selected,Values=null,PowerStateValues=null};}; activityPower.SelectionChanged+=(_,_)=>{if(!updating&&activityPower.SelectedItem is GalaxyFilterChoice selected)Filter=Filter with{ActivityAllPowers=selected.Key=="__allpowers",ActivityPowerName=selected.Key=="__allpowers"?null:selected.Label,ActivityInternalPowerId=selected.Key=="__allpowers"?null:Filter.OriginalPowerOptions.FirstOrDefault(p=>GalaxyPowerActivities.ChoiceKey(p.InternalPowerId)==selected.Key)?.InternalPowerId,OriginalActivityPowerIndex=null};}; activityType.SelectionChanged+=(_,_)=>{if(!updating&&activityType.SelectedItem is ComboBoxItem{Tag:GalaxyPowerActivity selected})Filter=Filter with{Activity=selected};}; useMinimumActivity.Checked+=(_,_)=>{if(!updating)Filter=Filter with{UseMinimumActivity=true};};useMinimumActivity.Unchecked+=(_,_)=>{if(!updating)Filter=Filter with{UseMinimumActivity=false};}; territoryActivityEnabled.Checked+=(_,_)=>{if(!updating)Filter=Filter with{TerritoryActivityFilterEnabled=true};};territoryActivityEnabled.Unchecked+=(_,_)=>{if(!updating)Filter=Filter with{TerritoryActivityFilterEnabled=false};}; minimumActivity.ValueChanged+=(_,e)=>{if(!updating)Filter=Filter with{MinimumActivity=e.NewValue};}; size.SelectionChanged+=(_,_)=>{if(!updating&&size.SelectedItem is ComboBoxItem{Tag:GalaxyFilterCategory selected})Filter=Filter with{SizeCategory=selected};}; commodityDirection.SelectionChanged+=(_,_)=>{if(!updating&&commodityDirection.SelectedItem is ComboBoxItem{Tag:GalaxyCommodityDirection selected})Filter=Filter with{CommodityDirection=selected,OriginalCommodityPriceMode=commodityDirection.SelectedIndex};}; void PopulationRangeChanged(NumberBox sender,NumberBoxValueChangedEventArgs args) {if(!updating&&double.IsFinite(populationMin.Value)&&double.IsFinite(populationMax.Value)&&populationMin.Value>=0&&populationMax.Value>=populationMin.Value)Filter=Filter with{PopulationMinimum=populationMin.Value,PopulationMaximum=populationMax.Value};} populationMin.ValueChanged+=PopulationRangeChanged;populationMax.ValueChanged+=PopulationRangeChanged; all.Click+=(_,_)=>Filter=Filter with{Mode=Filter.Mode==GalaxyMapMode.Realistic?GalaxyMapMode.Map:Filter.Mode,TerritoryPowerMask=Filter.UsesPowerTerritory?null:Filter.TerritoryPowerMask,OriginalCommodityUid=Filter.Category==GalaxyFilterCategory.Commodity?null:Filter.OriginalCommodityUid,Values=null,IncludeUnknown=false}; none.Click+=(_,_)=>Filter=Filter with{Mode=Filter.Mode==GalaxyMapMode.Realistic?GalaxyMapMode.Map:Filter.Mode,TerritoryPowerMask=Filter.UsesPowerTerritory?0:Filter.TerritoryPowerMask,OriginalCommodityUid=Filter.Category==GalaxyFilterCategory.Commodity?null:Filter.OriginalCommodityUid,Values=Filter.UsesPowerTerritory?null:new HashSet(),IncludeUnknown=false}; scoop.Click+=(_,_)=>Filter=Filter.WithCategory(GalaxyFilterCategory.StarClass) with{Values=new HashSet(GalaxyFilterDefinitions.ScoopableStarClasses),IncludeUnknown=false}; foreach(var toggle in new[]{grid,gridStalks,labels,regionNames,nebulaNames,constellations,galacticZones,galacticZoneNames,links,markers,route,background,reverseMouseCrane,unknown}){toggle.Checked+=ToggleChanged;toggle.Unchecked+=ToggleChanged;} range.ValueChanged+=(_,e)=>{if(!updating&&double.IsFinite(e.NewValue)&&e.NewValue is >=1 and <=1000)Filter=Filter with{JumpRange=e.NewValue};}; shipRange.Click+=(_,_)=>{if(ShipJumpRange is >=1 and <=1000)Filter=Filter with{JumpRange=ShipJumpRange};}; reset.Click+=(_,_)=>Filter=GalaxyMapFilter.Default; choiceSearch.TextChanged+=(_,_)=>Refresh(); root.Children.Add(BuildMarkerVisibilityControls()); Loaded+=(_,_)=>Refresh();Refresh(); } private static void Changed(DependencyObject sender,DependencyPropertyChangedEventArgs e)=>((GalaxyFilterPanel)sender).Refresh(); private void ToggleChanged(object sender,RoutedEventArgs e) { if(updating)return;Filter=Filter with{IncludeUnknown=unknown.IsChecked==true,ShowGrid=grid.IsChecked==true,ShowGridStalks=gridStalks.IsChecked==true,ReverseMouseCrane=reverseMouseCrane.IsChecked==true,ShowLinks=links.IsChecked==true,ShowLabels=labels.IsChecked==true,ShowRegionNames=regionNames.IsChecked==true,ShowNebulaNames=nebulaNames.IsChecked==true,ShowConstellations=constellations.IsChecked==true,ShowGalacticZonesPlane=galacticZones.IsChecked==true,ShowGalacticZoneNames=galacticZoneNames.IsChecked==true,ShowMarkers=markers.IsChecked==true,ShowRoute=route.IsChecked==true,ShowBackground=background.IsChecked==true}; } private void Refresh() { if(updating)return;updating=true; try { var f=Filter;mode.SelectedIndex=(int)f.Mode;category.SelectedItem=GalaxyFilterDefinitions.All.First(x=>x.Category==f.Category); populationLegend.Visibility=f.Mode!=GalaxyMapMode.Realistic&&f.Category==GalaxyFilterCategory.Population?Visibility.Visible:Visibility.Collapsed; populationLegendText.Text=$"{f.PopulationMinimum:N0} — {f.PopulationMaximum:N0} 人 · 线性配色"; powerStates.Visibility=f.Mode==GalaxyMapMode.Powerplay&&!f.UsesPowerOuter&&f.Category==GalaxyFilterCategory.Power?Visibility.Visible:Visibility.Collapsed; foreach(var check in powerStateChecks)check.Value.IsChecked=f.UsesPowerTerritory?GalaxyOriginalPowerFilters.StateSelected(f.TerritoryStateMask,check.Key):f.PowerStateValues is null||f.PowerStateValues.Contains(check.Key); RefreshSizeSelection(f); commodityDirection.Visibility=f.Category==GalaxyFilterCategory.Commodity||f.SizeCategory==GalaxyFilterCategory.Commodity?Visibility.Visible:Visibility.Collapsed;commodityDirection.SelectedIndex=f.CommodityPriceMode is 1 or 2?f.CommodityPriceMode:0; powerplayView.Visibility=f.Mode==GalaxyMapMode.Powerplay?Visibility.Visible:Visibility.Collapsed;powerplayView.SelectedIndex=(int)f.PowerplayView; activityControls.Visibility=f.Mode==GalaxyMapMode.Powerplay&&f.Category is GalaxyFilterCategory.Power or GalaxyFilterCategory.PowerActivityEligibility?Visibility.Visible:Visibility.Collapsed; activityPower.Header=f.UsesPowerOuter?"势力(总部定位)":"活动势力范围"; activityType.Visibility=useMinimumActivity.Visibility=minimumActivity.Visibility=activityNote.Visibility=f.UsesPowerOuter?Visibility.Collapsed:Visibility.Visible; territoryActivityEnabled.Visibility=f.UsesPowerOuter||f.Category==GalaxyFilterCategory.PowerActivityEligibility?Visibility.Collapsed:Visibility.Visible;territoryActivityEnabled.IsChecked=f.TerritoryActivityFilterEnabled; activityType.IsEnabled=useMinimumActivity.IsEnabled=f.UsesPowerActivityCounter; category.Visibility=f.UsesPowerOuter?Visibility.Collapsed:Visibility.Visible; powerHeadquarters.Visibility=f.Mode==GalaxyMapMode.Powerplay?Visibility.Visible:Visibility.Collapsed;powerHeadquarters.Command=LocatePowerHeadquartersCommand; thargoidPanel.Visibility=f.Mode==GalaxyMapMode.ThargoidWar||f.Category==GalaxyFilterCategory.ThargoidWar?Visibility.Visible:Visibility.Collapsed; RefreshThargoid(); RefreshCommunityGoals(); RefreshFleetControls(); RefreshMissionControls(); selectionActions.Visibility=choices.Visibility=choiceSearch.Visibility=f.UsesPowerOuter||f.Category==GalaxyFilterCategory.PowerActivityEligibility?Visibility.Collapsed:Visibility.Visible; commodityGroups.Visibility=f.Category==GalaxyFilterCategory.Commodity?Visibility.Visible:Visibility.Collapsed; if(f.Category==GalaxyFilterCategory.Commodity){choices.Visibility=Visibility.Collapsed;RefreshCommodityTree();} var powerChoices=new[]{new GalaxyFilterChoice("__allpowers","全部势力(原活动选项)")}.Concat(f.OriginalPowerOptions.Select(p=>new GalaxyFilterChoice(GalaxyPowerActivities.ChoiceKey(p.InternalPowerId),p.Name))).ToArray(); var powerSignature=string.Join('|',powerChoices.Select(p=>p.Key+":"+p.Label));if(activityChoicesSignature!=powerSignature){activityChoicesSignature=powerSignature;activityChoices=powerChoices;activityPower.ItemsSource=activityChoices;} activityPower.SelectedItem=activityChoices.FirstOrDefault(p=>f.ActivityAllPowers?p.Key=="__allpowers":f.ActivityInternalPowerId is {} powerId?p.Key==GalaxyPowerActivities.ChoiceKey(powerId):string.Equals(p.Label,f.ActivityPowerName,StringComparison.OrdinalIgnoreCase));activityType.SelectedIndex=(int)f.Activity; RefreshSavedActivityPower(); useMinimumActivity.IsChecked=f.UseMinimumActivity;minimumActivity.Value=f.MinimumActivity;minimumActivity.IsEnabled=f.UsesPowerActivityCounter&&f.UseMinimumActivity;minimumActivity.Header=$"最低近期活动强度 {f.MinimumActivity:P0}"; populationMin.Value=f.PopulationMinimum;populationMax.Value=f.PopulationMaximum;populationMin.IsEnabled=populationMax.IsEnabled=f.Mode!=GalaxyMapMode.Realistic&&(f.Category==GalaxyFilterCategory.Population||f.SizeCategory==GalaxyFilterCategory.Population); var definition=(GalaxyFilterDefinition)category.SelectedItem; var originalState=f.Category==GalaxyFilterCategory.State&&f.RequireOriginalStateFacts; var counts=choiceCounts;var recount=!ReferenceEquals(countedSystems,Systems)||countedCategory!=f.Category||countedCommodityDirection!=f.CommodityDirection||countedOriginalState!=originalState; if(recount){countedSystems=Systems;countedCategory=f.Category;countedCommodityDirection=f.CommodityDirection;countedOriginalState=originalState;counts.Clear();} var missing=0;var matching=0; foreach(var s in Systems) {var match=f.Evaluate(s);if(match.Unknown)missing++;if(recount&&match.Keys is {} keys)foreach(var key in keys.Distinct())counts[key]=counts.GetValueOrDefault(key)+1;if(match.Matches)matching++;} coverage.Text=$"{matching:N0} / {Systems.Count:N0} 星系 · {missing:N0} 个未知"; note.Text=f.Mode==GalaxyMapMode.Realistic?"写实模式依恒星光谱显示。选择筛选类别会切换至地图模式。":f.Category==GalaxyFilterCategory.Markers?GalaxyMarkerSources.Describe(f.Values):definition.Availability.Length>0?definition.Availability:"图例颜色对应已记录类别;灰色表示未知数据。"; if(f.UsesPowerTerritory)note.Text="势力与状态按原掩码同时筛选,须有当前游戏元数据。"+(f.OriginalPowerOptions.Count==0?"等待游戏实际势力表;不会用公开列表顺序代替原索引。":"清除势力仍保留原规则允许的无主、无势力旗标星系;要隐藏它们请取消“未占领”状态。")+"半选状态表示原保存值只含组内部分阶段。"; if(f.Mode!=GalaxyMapMode.Realistic&&f.Category==GalaxyFilterCategory.Services)note.Text="前10项为原版服务选项,后续为工具扩展服务。"+note.Text; if(f.Category==GalaxyFilterCategory.Commodity&&f.OriginalCommodityOptions.Count>0)note.Text=$"原定义源 {f.OriginalCommodityOptions.Count:N0} 项;库存不满足 {f.OriginalCommodityOptions.Count(o=>o.PublisherEligible==false):N0},待确认 {f.OriginalCommodityOptions.Count(o=>o.PublisherEligible is null):N0}。"+(f.UsesOriginalCommodity?"\n单项使用原进口/出口价格分类及无有效价格分支;未知隐藏。":"\n多项或非原定义使用公共站点供需查询;不冒充原区域余额。"); if(f.RequiresOriginalCommodity&&f.CommodityRequest is null)note.Text="原商品选择尚未与实际UID定义绑定;保留原选择,资料未知。不会改查之前的公共商品。"; information.Text=InformationStatus; importSettings.Command=ImportSettingsCommand;importStatus.Text=OriginalSettingsStatus; importDetails.Text=OriginalSettingsDetails; originalRouteFilter.IsChecked=f.OriginalRouteFilters.TryGetValue(f.Category,out var affects)?affects:null; if(!ReferenceEquals(renderedOriginalOptions,OriginalOptions)) {renderedOriginalOptions=OriginalOptions;originalOptions.Children.Clear();foreach(var entry in OriginalOptions??new Dictionary())originalOptions.Children.Add(new TextBlock{Text=entry.Key+" = "+entry.Value,FontSize=10,TextWrapping=TextWrapping.Wrap});} var extras=counts.Keys.Concat(f.OriginalOptionKeys.GetValueOrDefault(f.Category)??new HashSet()).Concat(f.Values??new HashSet()); var valueChoices=f.Category==GalaxyFilterCategory.PowerActivityEligibility?Array.Empty():QueryChoices??[]; var entries=definition.Choices.Concat(valueChoices).DistinctBy(x=>x.Key).Concat(extras.Distinct().Where(k=>!definition.Choices.Any(c=>c.Key==k)&&!valueChoices.Any(c=>c.Key==k)).Order().Select(k=>new GalaxyFilterChoice(k,k))); if(GalaxyStateFilterChoices.FromOriginal(f,counts.Keys) is {} originalStates)entries=originalStates; if(f.UsesPowerTerritory)entries=f.OriginalPowerOptions.Where(p=>p.Index is >=0 and <128).OrderBy(p=>p.Index).Select(p=>new GalaxyFilterChoice(GalaxyMapFilter.Normalize(p.Name),p.Name)); if(f.Category==GalaxyFilterCategory.Services) {var order=GalaxyOriginalServiceOptions.Keys.Select((key,index)=>(key,index)).ToDictionary(p=>p.key,p=>p.index);entries=entries.OrderBy(c=>order.GetValueOrDefault(c.Key,int.MaxValue));} var search=choiceSearch.Text.Trim();var visibleEntries=f.Category==GalaxyFilterCategory.Commodity?[]:entries.Where(x=>search.Length==0||x.Label.Contains(search,StringComparison.OrdinalIgnoreCase)||x.Key.Contains(search,StringComparison.OrdinalIgnoreCase)).Take(160).ToArray(); var signature=f.Category+"|"+string.Join("|",visibleEntries.Select(e=>e.Key+":"+e.Label)); if(signature!=renderedChoices){renderedChoices=signature;choices.Children.Clear();choiceRows.Clear();} foreach(var entry in visibleEntries) { var count=counts.GetValueOrDefault(entry.Key);var selected=f.UsesPowerTerritory?f.TerritoryPowerMask is null||f.OriginalPowerOptions.FirstOrDefault(p=>GalaxyMapFilter.Normalize(p.Name)==entry.Key) is {Index:>=0 and <128} option&&(f.TerritoryPowerMask.Value&(1u<<(option.Index&31)))!=0:f.Values is null||f.Values.Contains(entry.Key); if(!choiceRows.TryGetValue(entry.Key,out var controls)) { var row=new CheckBox{HorizontalAlignment=HorizontalAlignment.Stretch};var line=new StackPanel{Orientation=Orientation.Horizontal,Spacing=7}; var text=new TextBlock{FontSize=12,VerticalAlignment=VerticalAlignment.Center};var swatch=new Ellipse{Width=8,Height=8,VerticalAlignment=VerticalAlignment.Center}; line.Children.Add(swatch);line.Children.Add(text);row.Content=line;row.Checked+=(_,_)=>Select(entry.Key,true);row.Unchecked+=(_,_)=>Select(entry.Key,false); choiceRows[entry.Key]=controls=(row,text,swatch);choices.Children.Add(row); } controls.Row.IsChecked=selected;controls.Row.IsEnabled=f.Mode!=GalaxyMapMode.Realistic;controls.Text.Text=entry.Label+" "+count.ToString("N0"); controls.Swatch.Visibility=f.Category is GalaxyFilterCategory.Population or GalaxyFilterCategory.Markers?Visibility.Collapsed:Visibility.Visible; var colour=f.ColourForValue(entry.Key); if(controls.Swatch.Fill is SolidColorBrush oldBrush)oldBrush.Color=Color.FromArgb(255,colour.R,colour.G,colour.B);else controls.Swatch.Fill=new SolidColorBrush(Color.FromArgb(255,colour.R,colour.G,colour.B)); AutomationProperties.SetName(controls.Row,entry.Label+","+count+" 个星系"); } scoop.Visibility=f.Category==GalaxyFilterCategory.StarClass?Visibility.Visible:Visibility.Collapsed; unknown.IsChecked=f.IncludeUnknown;unknown.IsEnabled=f.Mode!=GalaxyMapMode.Realistic; grid.IsChecked=f.ShowGrid;gridStalks.IsChecked=f.ShowGridStalks;gridStalks.IsEnabled=f.ShowGrid;reverseMouseCrane.IsChecked=f.ReverseMouseCrane;labels.IsChecked=f.ShowLabels;links.IsChecked=f.ShowLinks;markers.IsChecked=f.ShowMarkers;route.IsChecked=f.ShowRoute;background.IsChecked=f.ShowBackground; regionNames.IsChecked=f.ShowRegionNames;nebulaNames.IsChecked=f.ShowNebulaNames;constellations.IsChecked=f.ShowConstellations;galacticZones.IsChecked=f.ShowGalacticZonesPlane;galacticZoneNames.IsChecked=f.ShowGalacticZoneNames; RefreshMarkerVisibilityControls(f); RefreshCurrentTradeControls(f); historicalTrade.IsChecked=f.ShowHistoricalTradeFlows;historicalTradeSource.SelectedIndex=(int)f.HistoricalTradeSource;historicalTradeSource.IsEnabled=f.ShowHistoricalTradeFlows;historicalTradeStatus.Text=HistoricalTradeStatus; RefreshHistoricalCommodityTree(f); range.Value=f.JumpRange;range.IsEnabled=f.ShowLinks;shipRange.IsEnabled=f.ShowLinks&&ShipJumpRange is >=1 and <=1000; } finally{updating=false;} } private void RefreshCommodityTree() { var available=(QueryChoices??[]).Concat(Filter.Values?.Select(k=>new GalaxyFilterChoice(k,k))??[]).Concat(Systems.SelectMany(s=>GalaxyMapFilter.Keys(s,GalaxyFilterCategory.Commodity,Filter.CommodityDirection)??[]).Select(k=>new GalaxyFilterChoice(k,k))); currentCommodityGroups=GalaxyCommodityTree.Build(available,originalOptions:Filter.OriginalCommodityOptions); var search=choiceSearch.Text.Trim(); bool Contains(string value)=>value.Contains(search,StringComparison.OrdinalIgnoreCase); var shown=currentCommodityGroups.Select(g=>search.Length==0||Contains(g.Label)||Contains(g.Key)?g:g with{Children=g.Children.Where(c=>Contains(c.Label)||Contains(c.Key)).ToArray()}).Where(g=>g.Children.Count>0).ToArray(); var signature=string.Join('|',shown.Select(g=>g.Key+":"+string.Join(',',g.Children.Select(c=>c.Key+"="+c.Label)))); if(commodityTreeSignature!=signature) { commodityTreeSignature=signature;commodityGroups.Children.Clear();commodityParents.Clear();commodityLeaves.Clear(); commodityGroups.Children.Add(new TextBlock{Text="按原商品类别分组;分类未读取的商品仍可单独选择。父类选择作用于整类,查找仅改变列表。",FontSize=11,TextWrapping=TextWrapping.Wrap}); foreach(var group in shown) { var complete=currentCommodityGroups.First(g=>g.Key==group.Key); var content=new StackPanel{Spacing=1};var parent=new CheckBox{Content="全选此类",IsThreeState=true};content.Children.Add(parent);commodityParents[group.Key]=(parent,complete); parent.Click+=(_,_)=> { if(updating)return; Filter=Filter with{OriginalCommodityUid=null,Values=GalaxyCommodityTree.SelectGroup(Filter.Values,currentCommodityGroups.SelectMany(g=>g.Children).Select(c=>c.Key),complete.Children.Select(c=>c.Key),GalaxyCommodityTree.Selected(Filter.Values,complete.Children)!=true)}; }; foreach(var child in group.Children) { var check=new CheckBox{Content=child.Label,HorizontalAlignment=HorizontalAlignment.Stretch};commodityLeaves[child.Key]=check;content.Children.Add(check); check.Checked+=(_,_)=>Select(child.Key,true);check.Unchecked+=(_,_)=>Select(child.Key,false); } var expander=new Expander{Header=group.Label+" · "+complete.Children.Count,Content=content,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch,IsExpanded=search.Length>0||commodityExpanded.GetValueOrDefault(group.Key)}; expander.Expanding+=(_,_)=>commodityExpanded[group.Key]=true;expander.Collapsed+=(_,_)=>commodityExpanded[group.Key]=false;commodityGroups.Children.Add(expander); } } foreach(var entry in commodityLeaves)entry.Value.IsChecked=Filter.Values is null||Filter.Values.Contains(entry.Key); foreach(var entry in commodityParents)entry.Value.Check.IsChecked=GalaxyCommodityTree.Selected(Filter.Values,entry.Value.Group.Children); } private void RefreshCommunityGoals() { communityGoalStatus.Text=CommunityGoalStatus; if(ReferenceEquals(renderedCommunityGoals,CommunityGoalTargets)&&ReferenceEquals(renderedCommunityGoalCommand,SelectCommunityGoalCommand))return; renderedCommunityGoals=CommunityGoalTargets;renderedCommunityGoalCommand=SelectCommunityGoalCommand;communityGoalTargets.Children.Clear(); foreach(var target in CommunityGoalTargets) { var content=new StackPanel{Spacing=2};content.Children.Add(new TextBlock{Text=target.Label,FontSize=12,TextWrapping=TextWrapping.Wrap});content.Children.Add(new TextBlock{Text=target.Source+" · 地址 "+target.SystemAddress,FontSize=10,TextWrapping=TextWrapping.Wrap}); var button=new Button{Content=content,Command=SelectCommunityGoalCommand,CommandParameter=target,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch};AutomationProperties.SetName(button,"定位社区活动 "+target.Label);communityGoalTargets.Children.Add(button); } } private void RefreshThargoid() { thargoidStatus.Text=ThargoidStatus; if(!ReferenceEquals(renderedThargoidCounts,ThargoidCounts)) { renderedThargoidCounts=ThargoidCounts;thargoidCounts.Children.Clear(); foreach(var count in ThargoidCounts.Where(c=>c.State!=38))thargoidCounts.Children.Add(new TextBlock{Text=count.Text,FontSize=12,TextWrapping=TextWrapping.Wrap}); if(ThargoidCounts.FirstOrDefault(c=>c.State==38) is {} pseudo)ToolTipService.SetToolTip(thargoidCounts,"原缓存状态38 · "+pseudo.Text); } var commandChanged=!ReferenceEquals(renderedThargoidCommand,SelectThargoidTargetCommand);renderedThargoidCommand=SelectThargoidTargetCommand; if(commandChanged||!ReferenceEquals(renderedThargoidSignals,ThargoidSignals)) {renderedThargoidSignals=ThargoidSignals;Targets(thargoidSignals,ThargoidSignals);} if(commandChanged||!ReferenceEquals(renderedThargoidRecommendations,ThargoidRecommendations)) {renderedThargoidRecommendations=ThargoidRecommendations;Targets(thargoidRecommendations,ThargoidRecommendations);} void Targets(StackPanel panel,IReadOnlyList targets) { panel.Children.Clear(); if(targets.Count==0){panel.Children.Add(new TextBlock{Text="缓存暂无条目;不代表已确认不存在。",FontSize=11,TextWrapping=TextWrapping.Wrap});return;} foreach(var target in targets) { var label=new StackPanel{Spacing=3};label.Children.Add(new TextBlock{Text=target.Title,TextWrapping=TextWrapping.Wrap,FontSize=12});label.Children.Add(new TextBlock{Text=target.Detail,TextWrapping=TextWrapping.Wrap,FontSize=10}); var button=new Button{Content=label,HorizontalAlignment=HorizontalAlignment.Stretch,HorizontalContentAlignment=HorizontalAlignment.Stretch,Command=SelectThargoidTargetCommand,CommandParameter=target}; AutomationProperties.SetName(button,"定位 "+target.Title);panel.Children.Add(button); } } } private void Select(string key,bool selected) { if(updating)return; if(Filter.UsesPowerTerritory) { if(Filter.OriginalPowerOptions.FirstOrDefault(p=>GalaxyMapFilter.Normalize(p.Name)==key) is not {Index:>=0 and <128} power)return; var mask=Filter.TerritoryPowerMask??Filter.OriginalPowerOptions.Where(p=>p.Index is >=0 and <128).Aggregate(0u,(bits,p)=>bits|(1u<<(p.Index&31))); var bit=1u<<(power.Index&31);Filter=Filter with{TerritoryPowerMask=selected?mask|bit:mask&~bit,Values=null};return; } if(GalaxyStateFilterChoices.FromOriginal(Filter,choiceCounts.Keys) is {} originalStates) {Filter=Filter with{Values=GalaxyStateFilterChoices.Select(Filter.Values,originalStates,key,selected)};return;} var definition=GalaxyFilterDefinitions.All.First(x=>x.Category==Filter.Category); var values=Filter.Values is {} existing?new HashSet(existing):definition.Choices.Select(x=>x.Key).Concat((QueryChoices??[]).Select(x=>x.Key)).Concat(Filter.Category==GalaxyFilterCategory.Commodity?currentCommodityGroups.SelectMany(g=>g.Children).Select(c=>c.Key):[]).Concat(Systems.SelectMany(s=>GalaxyMapFilter.Keys(s,Filter.Category,Filter.CommodityDirection)??[])).ToHashSet(); if(selected)values.Add(key);else values.Remove(key);Filter=Filter with{Values=values,OriginalCommodityUid=Filter.Category==GalaxyFilterCategory.Commodity?null:Filter.OriginalCommodityUid}; } }