# M16.8.15.5.3.4 v2.6
# Filter状態が残っている間だけ前回条件・値を復元する。
# 「この列のFilter解除」等では DisplayFilterStates から削除されるため、
# 解除後に再表示した場合は自動的に初期状態になる。
$savedFilterState =
Get-HashEditorDisplayFilterState `
-ColumnName $ColumnName
if ($null -ne $savedFilterState) {
$savedConditionDisplayText =
Get-HashEditorFilterConditionDisplayText `
-Condition ([string]$savedFilterState.Condition) `
-InputType $filterInputType
$savedConditionIndex =
$comboCondition.Items.IndexOf(
[string]$savedConditionDisplayText
)
if ($savedConditionIndex -ge 0) {
$comboCondition.SelectedIndex =
$savedConditionIndex
}
if ($isChoiceFilter) {
$savedChoiceIndex =
$choiceValue.Items.IndexOf(
[string]$savedFilterState.Value
)
if ($savedChoiceIndex -ge 0) {
$choiceValue.SelectedIndex =
$savedChoiceIndex
}
}
elseif ($isBooleanFilter) {
$savedBooleanIndex =
$booleanValue.Items.IndexOf(
[string]$savedFilterState.Value
)
if ($savedBooleanIndex -ge 0) {
$booleanValue.SelectedIndex =
$savedBooleanIndex
}
}
elseif ($isDateFilter) {
$dateValue.Text =
[string]$savedFilterState.Value
}
else {
$savedMultiValues =
@(
ConvertFrom-HashEditorMultiFilterValue `
-Value ([string]$savedFilterState.Value)
)
if ($savedMultiValues.Count -gt 0) {
$textValue.Text =
[string]$savedMultiValues[0]
}
}
}
$updateValueInputState = {
$condition =
ConvertFrom-HashEditorFilterConditionDisplayText `
-DisplayText ([string]$comboCondition.SelectedItem)
$needsValue =
Test-HashEditorTextFilterNeedsValue `
-Condition $condition
if ($isChoiceFilter) {
$choiceValue.Enabled =
$needsValue
if (
$needsValue -and
$choiceValue.Items.Count -gt 0 -and
$choiceValue.SelectedIndex -lt 0
) {
$choiceValue.SelectedIndex =
0
}
if (-not $needsValue) {
$choiceValue.SelectedIndex =
-1
}
}
elseif ($isBooleanFilter) {
$booleanValue.Enabled =
$needsValue
if (
$needsValue -and
$booleanValue.Items.Count -gt 0 -and
$booleanValue.SelectedIndex -lt 0
) {
$booleanValue.SelectedIndex =
0
}
if (-not $needsValue) {
$booleanValue.SelectedIndex =
-1
}
}
elseif ($isDateFilter) {
$dateNeedsValue =
Test-HashEditorDateFilterNeedsValue `
-Condition $condition
$dateValue.Enabled =
$dateNeedsValue
$dateCalendarButton.Enabled =
$dateNeedsValue
$dateNoteMark.Enabled =
$dateNeedsValue
$dateInputHint.Enabled =
$dateNeedsValue
if (-not $dateNeedsValue) {
$dateValue.Text =
""
}
}
else {
$textValue.Enabled =
$needsValue
$buttonAddMultiValue.Visible =
$needsValue
$buttonAddMultiValue.Enabled =
$needsValue
if ($needsValue) {
$labelValue.Text =
"値1"
$textValue.Size =
New-Object System.Drawing.Size(
364,
32
)
foreach (
$rowState in @(
$multiValueRows
)
) {
$rowState.Label.Visible =
$true
$rowState.TextBox.Visible =
$true
$rowState.TextBox.Enabled =
$true
$rowState.RemoveButton.Visible =
$true
}
}
else {
$labelValue.Text =
"値"
$textValue.Size =
New-Object System.Drawing.Size(
400,
32
)
$textValue.Text =
""
foreach (
$rowState in @(
$multiValueRows
)
) {
if ($null -ne $rowState.Label) {
$popup.Controls.Remove(
$rowState.Label
)
$rowState.Label.Dispose()
}
if ($null -ne $rowState.TextBox) {
$popup.Controls.Remove(
$rowState.TextBox
)
$rowState.TextBox.Dispose()
}
if ($null -ne $rowState.RemoveButton) {
$popup.Controls.Remove(
$rowState.RemoveButton
)
$rowState.RemoveButton.Dispose()
}
}
$multiValueRows.Clear()
}
}
}
$dateDeleteMode =
@{
Value = $false
}
$dateFormatGuard =
@{
Value = $false
}
$dateValue.Add_KeyDown({
param(
$sender,
$e
)
if (
$e.KeyCode -eq [System.Windows.Forms.Keys]::Back -or
$e.KeyCode -eq [System.Windows.Forms.Keys]::Delete
) {
$dateDeleteMode.Value =
$true
}
})
$dateValue.Add_TextChanged({
param(
$sender,
$e
)
if ($dateFormatGuard.Value) {
return
}
if ($dateDeleteMode.Value) {
$dateDeleteMode.Value =
$false
return
}
$originalText =
[string]$sender.Text
$formattedText =
Format-HashEditorFilterDateTypingText `
-Text $originalText
if ($formattedText -eq $originalText) {
return
}
$dateFormatGuard.Value =
$true
try {
$sender.Text =
$formattedText
$sender.SelectionStart =
$sender.Text.Length
}
finally {
$dateFormatGuard.Value =
$false
}
})
$dateValue.Add_Leave({
param(
$sender,
$e
)
$parsedDate =
ConvertTo-HashEditorFilterDate `
-Value $sender.Text
if ($null -ne $parsedDate) {
$dateFormatGuard.Value =
$true
try {
$sender.Text =
([datetime]$parsedDate).ToString(
"yyyy/MM/dd"
)
}
finally {
$dateFormatGuard.Value =
$false
}
}
})
$dateCalendarButton.Add_Click({
param(
$sender,
$e
)
if (-not $isDateFilter) {
return
}
$calendarForm =
New-Object System.Windows.Forms.Form
# M16.8.13.5 v7
# 詳細入力画面のCalendarポップアップと同じ方式に統一。
# タイトルバー・×・サイズ変更枠・余分な右側領域を表示しない。
$calendarForm.FormBorderStyle =
[System.Windows.Forms.FormBorderStyle]::None
$calendarForm.StartPosition =
[System.Windows.Forms.FormStartPosition]::Manual
$calendarForm.ShowInTaskbar =
$false
$calendarForm.MinimizeBox =
$false
$calendarForm.MaximizeBox =
$false
$calendarForm.ControlBox =
$false
$calendarForm.SizeGripStyle =
[System.Windows.Forms.SizeGripStyle]::Hide
$calendarForm.AutoScaleMode =
[System.Windows.Forms.AutoScaleMode]::None
$monthCalendar =
New-Object System.Windows.Forms.MonthCalendar
$monthCalendar.MaxSelectionCount =
1
$parsedCurrent =
ConvertTo-HashEditorFilterDate `
-Value $dateValue.Text
if ($null -ne $parsedCurrent) {
$monthCalendar.SetDate(
[datetime]$parsedCurrent
)
}
# M16.8.13.5 v8
# MonthCalendar.Size は環境/DPIによって余白を含む場合がある。
# 1か月表示の実寸である SingleMonthSize を明示的に使い、
# 右側・下側の余白を作らない。
$singleMonthSize =
$monthCalendar.SingleMonthSize
$monthCalendar.Size =
$singleMonthSize
$monthCalendar.Margin =
New-Object System.Windows.Forms.Padding(
0
)
$monthCalendar.Location =
New-Object System.Drawing.Point(
0,
0
)
$calendarForm.Padding =
New-Object System.Windows.Forms.Padding(
0
)
$calendarForm.ClientSize =
$singleMonthSize
[void]$calendarForm.Controls.Add(
$monthCalendar
)
$calendarState =
@{
DateTextBox = $dateValue
}
$calendarForm.Tag =
$calendarState
$monthCalendar.Tag =
$calendarState
# Calendarボタンの直下へ表示。
$buttonBottomPoint =
New-Object System.Drawing.Point(
0,
$sender.Height
)
$buttonScreenPoint =
$sender.PointToScreen(
$buttonBottomPoint
)
# Calendarの右端とボタンの右端を揃える。
# これによりポップアップはボタンから左側へ展開し、
# 「右下にぶら下がる」見え方を避ける。
$calendarLocation =
New-Object System.Drawing.Point(
(
$buttonScreenPoint.X +
$sender.Width -
$calendarForm.Width
),
$buttonScreenPoint.Y
)
$calendarScreen =
[System.Windows.Forms.Screen]::FromPoint(
$calendarLocation
)
$workingArea =
$calendarScreen.WorkingArea
if (
(
$calendarLocation.X +
$calendarForm.Width
) -gt
$workingArea.Right
) {
$calendarLocation.X =
$workingArea.Right -
$calendarForm.Width
}
if (
(
$calendarLocation.Y +
$calendarForm.Height
) -gt
$workingArea.Bottom
) {
$buttonTopPoint =
New-Object System.Drawing.Point(
0,
0
)
$buttonTopScreenPoint =
$sender.PointToScreen(
$buttonTopPoint
)
$calendarLocation.Y =
$buttonTopScreenPoint.Y -
$calendarForm.Height
}
if ($calendarLocation.X -lt $workingArea.Left) {
$calendarLocation.X = $workingArea.Left
}
if ($calendarLocation.Y -lt $workingArea.Top) {
$calendarLocation.Y = $workingArea.Top
}
$calendarForm.Location =
$calendarLocation
$monthCalendar.Add_DateSelected({
param(
$calendarSender,
$calendarEvent
)
$state =
$calendarSender.Tag
if (
$null -ne $state -and
$null -ne $state.DateTextBox
) {
$state.DateTextBox.Text =
$calendarEvent.Start.ToString(
"yyyy/MM/dd"
)
}
$popupForm =
$calendarSender.FindForm()
if (
$null -ne $popupForm -and
-not $popupForm.IsDisposed
) {
$popupForm.Close()
}
})
# Calendar外クリックで閉じる。
$calendarForm.Add_Deactivate({
param(
$formSender,
$eventArgs
)
if (
$null -ne $formSender -and
-not $formSender.IsDisposed
) {
$formSender.Close()
}
})
$calendarForm.Add_FormClosed({
param(
$formSender,
$eventArgs
)
$state =
$formSender.Tag
if (
$null -ne $state -and
$null -ne $state.DateTextBox
) {
[void]$state.DateTextBox.Focus()
}
# M16.8.13.6.5 v2
# Calendar終了後はFilter Popupへ明示的にフォーカスを戻す。
# PowerShellコンソールが前面へ出るのを防ぐ。
if (
$null -ne $popup -and
-not $popup.IsDisposed
) {
$popup.Activate()
[void]$popup.Focus()
$popup.BringToFront()
}
})
# Filter Popupを所有者として非モーダル表示。
# 所有関係を明示してCalendar終了後の前面復帰先を安定させる。
$calendarForm.Show(
$popup
)
$calendarForm.Activate()
})
$buttonApply =
New-Object System.Windows.Forms.Button
$buttonApply.Text =
"適用"
$buttonApply.Font =
$filterButtonFont
$buttonApply.Location =
New-Object System.Drawing.Point(157, 126)
$buttonApply.Size =
New-Object System.Drawing.Size(72, 28)
$buttonClear =
New-Object System.Windows.Forms.Button
$buttonClear.Text =
"解除"
$buttonClear.Font =
$filterButtonFont
$buttonClear.Location =
New-Object System.Drawing.Point(239, 126)
$buttonClear.Size =
New-Object System.Drawing.Size(72, 28)
$buttonClose =
New-Object System.Windows.Forms.Button
$buttonClose.Text =
"閉じる"
$buttonClose.Font =
$filterButtonFont
$buttonClose.Location =
New-Object System.Drawing.Point(321, 126)
$buttonClose.Size =
New-Object System.Drawing.Size(72, 28)
# M16.8.15.5.3.4 v1.1
# Tab順を動的入力欄の数に合わせて再構築する。
$updateMultiValueTabOrder = {
$tabIndex =
0
$comboCondition.TabIndex =
$tabIndex
$tabIndex++
if (
-not $isChoiceFilter -and
-not $isBooleanFilter -and
-not $isDateFilter
) {
$textValue.TabIndex =
$tabIndex
$tabIndex++
foreach (
$rowState in @(
$multiValueRows
)
) {
if ($null -ne $rowState.TextBox) {
$rowState.TextBox.TabIndex =
$tabIndex
$rowState.TextBox.TabStop =
$true
$tabIndex++
}
}
}
elseif ($isChoiceFilter) {
$choiceValue.TabIndex =
$tabIndex
$tabIndex++
}
elseif ($isBooleanFilter) {
$booleanValue.TabIndex =
$tabIndex
$tabIndex++
}
elseif ($isDateFilter) {
$dateValue.TabIndex =
$tabIndex
$tabIndex++
}
$buttonApply.TabIndex =
$tabIndex
$tabIndex++
$buttonClear.TabIndex =
$tabIndex
$tabIndex++
$buttonClose.TabIndex =
$tabIndex
}
# M16.8.15.5.3.4 v2
# Text列では、値が必要な全条件で複数値入力を使用する。
$updateMultiValueLayout = {
$condition =
ConvertFrom-HashEditorFilterConditionDisplayText `
-DisplayText ([string]$comboCondition.SelectedItem)
$isTextFilter =
(
-not $isChoiceFilter -and
-not $isBooleanFilter -and
-not $isDateFilter
)
$needsValue =
Test-HashEditorTextFilterNeedsValue `
-Condition $condition
$useMultiValueUi =
(
$isTextFilter -and
$needsValue
)
if (-not $useMultiValueUi) {
if ($isTextFilter) {
$multiValueHint.Visible =
$false
}
$popup.ClientSize =
New-Object System.Drawing.Size(
550,
166
)
$buttonY =
126
$buttonApply.Location =
New-Object System.Drawing.Point(
157,
$buttonY
)
$buttonClear.Location =
New-Object System.Drawing.Point(
239,
$buttonY
)
$buttonClose.Location =
New-Object System.Drawing.Point(
321,
$buttonY
)
& $updateMultiValueTabOrder
return
}
$multiValueHint.Visible =
$true
$rowIndex =
0
foreach (
$rowState in @(
$multiValueRows
)
) {
$rowNumber =
$rowIndex + 2
$rowY =
66 + ($rowNumber - 1) * 35
$rowState.Label.Text =
"値" + [string]$rowNumber
$rowState.Label.Location =
New-Object System.Drawing.Point(
16,
($rowY + 6)
)
$rowState.TextBox.Location =
New-Object System.Drawing.Point(
92,
$rowY
)
$rowState.RemoveButton.Location =
New-Object System.Drawing.Point(
460,
($rowY - 3)
)
$rowIndex++
}
$extraHeight =
$multiValueRows.Count * 35
$hintY =
92 + $extraHeight
$multiValueHint.Location =
New-Object System.Drawing.Point(
92,
$hintY
)
$buttonY =
124 + $extraHeight
$popup.ClientSize =
New-Object System.Drawing.Size(
550,
(164 + $extraHeight)
)
$buttonApply.Location =
New-Object System.Drawing.Point(
157,
$buttonY
)
$buttonClear.Location =
New-Object System.Drawing.Point(
239,
$buttonY
)
$buttonClose.Location =
New-Object System.Drawing.Point(
321,
$buttonY
)
& $updateMultiValueTabOrder
}
$buttonAddMultiValue.Add_Click({
$rowLabel =
New-Object System.Windows.Forms.Label
$rowLabel.AutoSize =
$true
$rowLabel.Font =
$filterFont
# M16.8.15.5.3.4 v2.6
# 値2以降も値1と同じ入力可能ComboBox。
$rowTextBox =
New-Object System.Windows.Forms.ComboBox
$rowTextBox.DropDownStyle =
[System.Windows.Forms.ComboBoxStyle]::DropDown
$rowTextBox.AutoCompleteMode =
[System.Windows.Forms.AutoCompleteMode]::SuggestAppend
$rowTextBox.AutoCompleteSource =
[System.Windows.Forms.AutoCompleteSource]::ListItems
$rowTextBox.Font =
$filterFont
$rowTextBox.Size =
New-Object System.Drawing.Size(
364,
32
)
foreach ($textFilterItem in @($textFilterItems)) {
[void]$rowTextBox.Items.Add(
[string]$textFilterItem
)
}
Set-HashEditorFilterComboLimitNote `
-ComboBox $rowTextBox
$rowRemoveButton =
New-Object System.Windows.Forms.Button
$rowRemoveButton.Text =
"-"
$rowRemoveButton.Font =
$filterButtonFont
$rowRemoveButton.Size =
New-Object System.Drawing.Size(
32,
28
)
$rowRemoveButton.TabStop =
$false
$rowState =
@{
Label = $rowLabel
TextBox = $rowTextBox
RemoveButton = $rowRemoveButton
}
$rowRemoveButton.Tag =
$rowState
$rowRemoveButton.Add_Click({
param(
$sender,
$eventArgs
)
$target =
$sender.Tag
if ($null -eq $target) {
return
}
[void]$multiValueRows.Remove(
$target
)
foreach (
$control in @(
$target.Label,
$target.TextBox,
$target.RemoveButton
)
) {
if ($null -ne $control) {
$popup.Controls.Remove(
$control
)
$control.Dispose()
}
}
& $updateMultiValueLayout
})
[void]$multiValueRows.Add(
$rowState
)
[void]$popup.Controls.Add(
$rowLabel
)
[void]$popup.Controls.Add(
$rowTextBox
)
[void]$popup.Controls.Add(
$rowRemoveButton
)
& $updateMultiValueLayout
[void]$rowTextBox.Focus()
})
$comboCondition.Add_SelectedIndexChanged({
& $updateValueInputState
& $updateMultiValueLayout
})
& $updateValueInputState
& $updateMultiValueLayout
# M16.8.15.5.3.4 v2
# 保存済みText Filterは、条件を問わず2件目以降の値欄も復元する。
if (
$null -ne $savedFilterState -and
-not $isChoiceFilter -and
-not $isBooleanFilter -and
-not $isDateFilter -and
(
Test-HashEditorTextFilterNeedsValue `
-Condition ([string]$savedFilterState.Condition)
)
) {
$savedMultiValues =
@(
ConvertFrom-HashEditorMultiFilterValue `
-Value ([string]$savedFilterState.Value)
)
for (
$savedIndex = 1;
$savedIndex -lt $savedMultiValues.Count;
$savedIndex++
) {
$buttonAddMultiValue.PerformClick()
if ($multiValueRows.Count -gt 0) {
$multiValueRows[
$multiValueRows.Count - 1
].TextBox.Text =
[string]$savedMultiValues[$savedIndex]
}
}
& $updateMultiValueLayout
}
$buttonApply.Add_Click({
$filterValue =
""
if ($isChoiceFilter) {
if (
$choiceValue.SelectedIndex -ge 0
) {
$filterValue =
[string]$choiceValue.SelectedItem
}
}
elseif ($isBooleanFilter) {
if (
$booleanValue.SelectedIndex -ge 0
) {
$filterValue =
[string]$booleanValue.SelectedItem
}
}
elseif ($isDateFilter) {
$filterValue =
[string]$dateValue.Text
}
else {
$filterValue =
[string]$textValue.Text
}
$filterCondition =
ConvertFrom-HashEditorFilterConditionDisplayText `
-DisplayText ([string]$comboCondition.SelectedItem)
if (
-not $isChoiceFilter -and
-not $isBooleanFilter -and
-not $isDateFilter -and
(
Test-HashEditorTextFilterNeedsValue `
-Condition $filterCondition
)
) {
$multiValues =
New-Object System.Collections.ArrayList
if (
-not [string]::IsNullOrWhiteSpace(
[string]$textValue.Text
)
) {
[void]$multiValues.Add(
[string]$textValue.Text
)
}
foreach (
$rowState in @(
$multiValueRows
)
) {
if (
$null -ne $rowState.TextBox -and
-not [string]::IsNullOrWhiteSpace(
[string]$rowState.TextBox.Text
)
) {
[void]$multiValues.Add(
[string]$rowState.TextBox.Text
)
}
}
$filterValue =
ConvertTo-HashEditorMultiFilterValue `
-Values @($multiValues)
}
if (
Invoke-HashEditorDisplayFilter `
-Grid $Grid `
-ColumnName $ColumnName `
-Condition $filterCondition `
-Value $filterValue
) {
$popup.Close()
}
})
$buttonClear.Add_Click({
if (
Test-HashEditorDisplayFilterActive
) {
[void](
Clear-HashEditorDisplayFilterColumn `
-Grid $Grid `
-ColumnName $ColumnName `
-Silent
)
}
$popup.Close()
})
$buttonClose.Add_Click({
$popup.Close()
})
$popup.AcceptButton =
$buttonApply
$popup.CancelButton =
$buttonClose
[void]$popup.Controls.Add($labelCondition)
[void]$popup.Controls.Add($comboCondition)
[void]$popup.Controls.Add($labelValue)
[void]$popup.Controls.Add($textValue)
[void]$popup.Controls.Add($buttonAddMultiValue)
[void]$popup.Controls.Add($multiValueHint)
[void]$popup.Controls.Add($choiceValue)
[void]$popup.Controls.Add($booleanValue)
[void]$popup.Controls.Add($dateValue)
[void]$popup.Controls.Add($dateCalendarButton)
[void]$popup.Controls.Add($dateNoteMark)
[void]$popup.Controls.Add($dateInputHint)
[void]$popup.Controls.Add($buttonApply)
[void]$popup.Controls.Add($buttonClear)
[void]$popup.Controls.Add($buttonClose)
# M16.8.29.3.15
# 正式仕様 COL-003: 対象列の3番目の表示データ行右端を基準にする。
#
# 縦:
# Popup上端 = 対象列の3番目の表示データ行セル上端
#
# 横:
# Popup左端 = 対象列右端 - 20px
#
# 表示データが3行未満の場合は、最後の表示データ行を基準にする。
# データ行がない場合だけ、従来どおり列ヘッダー右端を基準にする。
$targetColumn =
$Grid.Columns[$ColumnName]
$visibleDataRows =
@(
foreach ($gridRow in $Grid.Rows) {
if (
$null -ne $gridRow -and
$gridRow.Visible -and
-not $gridRow.IsNewRow
) {
$gridRow
}
}
)
$targetRow =
$null
if ($visibleDataRows.Count -ge 3) {
$targetRow =
$visibleDataRows[2]
}
elseif ($visibleDataRows.Count -gt 0) {
$targetRow =
$visibleDataRows[$visibleDataRows.Count - 1]
}
if ($null -ne $targetRow) {
$targetCellRect =
$Grid.GetCellDisplayRectangle(
$targetColumn.Index,
$targetRow.Index,
$true
)
$targetCellPoint =
New-Object System.Drawing.Point(
$targetCellRect.Right,
$targetCellRect.Top
)
$targetScreenPoint =
$Grid.PointToScreen(
$targetCellPoint
)
$popupLocation =
New-Object System.Drawing.Point(
($targetScreenPoint.X - 20),
$targetScreenPoint.Y
)
}
else {
# データ行がない場合は対象列ヘッダー右端を基準にする。
$headerRect =
$Grid.GetCellDisplayRectangle(
$targetColumn.Index,
-1,
$true
)
$headerPoint =
New-Object System.Drawing.Point(
$headerRect.Right,
$headerRect.Bottom
)
$headerScreenPoint =
$Grid.PointToScreen(
$headerPoint
)
$popupLocation =
New-Object System.Drawing.Point(
($headerScreenPoint.X - 20),
$headerScreenPoint.Y
)
}
# マルチモニターを含め、Popup全体が画面内に収まるよう補正する。
$popupScreen =
[System.Windows.Forms.Screen]::FromPoint(
$popupLocation
)
$workingArea =
$popupScreen.WorkingArea
if ($popupLocation.X -lt $workingArea.Left) {
$popupLocation.X =
$workingArea.Left
}
if (
(
$popupLocation.X +
$popup.Width
) -gt
$workingArea.Right
) {
$popupLocation.X =
$workingArea.Right -
$popup.Width
}
if ($popupLocation.Y -lt $workingArea.Top) {
$popupLocation.Y =
$workingArea.Top
}
if (
(
$popupLocation.Y +
$popup.Height
) -gt
$workingArea.Bottom
) {
$popupLocation.Y =
$workingArea.Bottom -
$popup.Height
}
$popup.Location =
$popupLocation
$owner =
$Grid.FindForm()
if ($null -ne $owner) {
[void]$popup.ShowDialog($owner)
}
else {
[void]$popup.ShowDialog()
}
$popup.Dispose()
}