хз
This commit is contained in:
parent
ad2025c52b
commit
5d23e7f97d
2 changed files with 75 additions and 62 deletions
|
|
@ -4,23 +4,34 @@
|
||||||
x:Class="NotesDataAnalyst.GraphPage"
|
x:Class="NotesDataAnalyst.GraphPage"
|
||||||
Title="GraphPage">
|
Title="GraphPage">
|
||||||
|
|
||||||
<ContentPage.ToolbarItems>
|
|
||||||
<ToolbarItem Text="Add Node" Clicked="OnAddNodeClicked"/>
|
|
||||||
<ToolbarItem Text="Добавить дочернюю" Clicked="OnChildClicked"/>
|
|
||||||
<ToolbarItem Text="Изменить размер" Clicked="OnResizeNodeClicked" />
|
|
||||||
</ContentPage.ToolbarItems>
|
|
||||||
|
|
||||||
<ContentPage.Content>
|
<ContentPage.Content>
|
||||||
<AbsoluteLayout>
|
<Grid RowDefinitions="*,Auto" Padding="10">
|
||||||
<GraphicsView x:Name="canvasView"
|
<!-- Канва для рисования занимает верхнюю часть экрана -->
|
||||||
HeightRequest="800"
|
<ScrollView x:Name="scrollView" Grid.Row="0" Orientation="Vertical">
|
||||||
WidthRequest="800" />
|
<AbsoluteLayout Grid.Row="0">
|
||||||
|
<GraphicsView x:Name="canvasView"
|
||||||
|
HeightRequest="8000"
|
||||||
|
WidthRequest="8000"
|
||||||
|
/>
|
||||||
|
</AbsoluteLayout>
|
||||||
|
</ScrollView>
|
||||||
|
<!-- Панель с кнопками внизу -->
|
||||||
|
<ScrollView Grid.Row="1" Orientation="Horizontal" HorizontalScrollBarVisibility="Always" VerticalScrollBarVisibility="Never">
|
||||||
|
<StackLayout Orientation="Horizontal" Spacing="1" Padding="20">
|
||||||
|
<Button Text="Добавить" Clicked="OnAddNodeClicked" WidthRequest="100"/>
|
||||||
|
<Button Text="Добавить дочернюю" Clicked="OnChildClicked" />
|
||||||
|
<Button Text="Изменить размер" Clicked="OnResizeNodeClicked" />
|
||||||
|
<Button Text="Редактировать текст" Clicked="OnEditTextClicked" />
|
||||||
|
</StackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
<!-- Поле для редактирования текста -->
|
<!-- Поле для редактирования текста -->
|
||||||
<Entry x:Name="textEditor"
|
<Entry x:Name="textEditor"
|
||||||
IsVisible="False"
|
IsVisible="False"
|
||||||
BackgroundColor="White"
|
BackgroundColor="White"
|
||||||
TextColor="Black"
|
TextColor="Black"
|
||||||
FontSize="18" />
|
FontSize="18"
|
||||||
</AbsoluteLayout>
|
Completed="OnTextEditorCompleted" />
|
||||||
|
</Grid>
|
||||||
</ContentPage.Content>
|
</ContentPage.Content>
|
||||||
</ContentPage>
|
</ContentPage>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ namespace NotesDataAnalyst
|
||||||
private readonly List<GraphNode> _nodes = new();
|
private readonly List<GraphNode> _nodes = new();
|
||||||
private readonly List<GraphConnection> _connections = new();
|
private readonly List<GraphConnection> _connections = new();
|
||||||
private GraphNode _selectedNode;
|
private GraphNode _selectedNode;
|
||||||
private bool _isResizing = false;
|
private bool _isScrollingBlocked = false;
|
||||||
|
|
||||||
|
|
||||||
public GraphPage()
|
public GraphPage()
|
||||||
{
|
{
|
||||||
|
|
@ -27,6 +28,41 @@ namespace NotesDataAnalyst
|
||||||
var tapGesture = new TapGestureRecognizer();
|
var tapGesture = new TapGestureRecognizer();
|
||||||
tapGesture.Tapped += OnCanvasTapped;
|
tapGesture.Tapped += OnCanvasTapped;
|
||||||
canvasView.GestureRecognizers.Add(tapGesture);
|
canvasView.GestureRecognizers.Add(tapGesture);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void OnEditTextClicked(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// Проверяем, выбрана ли нода
|
||||||
|
if (_selectedNode == null)
|
||||||
|
{
|
||||||
|
await DisplayAlert("Ошибка", "Сначала выберите ноду", "OK");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Показываем поле для редактирования текста и заполняем его текущим текстом ноды
|
||||||
|
textEditor.IsVisible = true;
|
||||||
|
textEditor.Text = _selectedNode.Text;
|
||||||
|
|
||||||
|
// Ставим фокус на текстовое поле для ввода
|
||||||
|
textEditor.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Обработчик завершения редактирования текста
|
||||||
|
private void OnTextEditorCompleted(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_selectedNode != null)
|
||||||
|
{
|
||||||
|
// Обновляем текст ноды с введенным значением
|
||||||
|
_selectedNode.Text = textEditor.Text;
|
||||||
|
|
||||||
|
// Скрываем поле для редактирования текста
|
||||||
|
textEditor.IsVisible = false;
|
||||||
|
|
||||||
|
// Перерисовываем канву для обновления отображения текста
|
||||||
|
canvasView.Invalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void OnResizeNodeClicked(object sender, EventArgs e)
|
private async void OnResizeNodeClicked(object sender, EventArgs e)
|
||||||
|
|
@ -61,16 +97,13 @@ namespace NotesDataAnalyst
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async void OnAddNodeClicked(object sender, EventArgs e)
|
private async void OnAddNodeClicked(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
var newNode = new GraphNode
|
var newNode = new GraphNode
|
||||||
{
|
{
|
||||||
Text = "Новая нода",
|
Text = "Новая нода",
|
||||||
Position = new Point(100, 200),
|
Position = new Point(100, 200),
|
||||||
Size = new Size(100, 50),
|
Size = new Size(100, 50),
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_nodes.Add(newNode);
|
_nodes.Add(newNode);
|
||||||
|
|
@ -98,7 +131,6 @@ namespace NotesDataAnalyst
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void OnCanvasTapped(object sender, TappedEventArgs e)
|
private void OnCanvasTapped(object sender, TappedEventArgs e)
|
||||||
{
|
{
|
||||||
var tapPosition = e.GetPosition((View)sender);
|
var tapPosition = e.GetPosition((View)sender);
|
||||||
|
|
@ -120,65 +152,35 @@ namespace NotesDataAnalyst
|
||||||
{
|
{
|
||||||
if (_selectedNode == null) return;
|
if (_selectedNode == null) return;
|
||||||
|
|
||||||
|
// Начало перетаскивания
|
||||||
if (e.StatusType == GestureStatus.Started)
|
if (e.StatusType == GestureStatus.Started)
|
||||||
{
|
{
|
||||||
|
// Запоминаем начальную позицию касания и ноды
|
||||||
|
_initialTouchPosition = new Point(e.TotalX, e.TotalY);
|
||||||
_initialNodePosition = _selectedNode.Position;
|
_initialNodePosition = _selectedNode.Position;
|
||||||
_initialTouchPosition = new PointF((float)e.TotalX, (float)e.TotalY);
|
|
||||||
_initialNodeSize = _selectedNode.Size;
|
|
||||||
|
|
||||||
_isResizing = IsOnResizeHandle(_selectedNode, _initialTouchPosition);
|
|
||||||
}
|
}
|
||||||
|
// Перемещение
|
||||||
else if (e.StatusType == GestureStatus.Running)
|
else if (e.StatusType == GestureStatus.Running)
|
||||||
{
|
{
|
||||||
var deltaX = (float)e.TotalX - _initialTouchPosition.X;
|
var deltaX = e.TotalX - _initialTouchPosition.X; // Разница с начальной точкой
|
||||||
var deltaY = (float)e.TotalY - _initialTouchPosition.Y;
|
var deltaY = e.TotalY - _initialTouchPosition.Y;
|
||||||
|
|
||||||
if (_isResizing)
|
// Перемещаем ноду относительно её начальной позиции
|
||||||
{
|
_selectedNode.Position = new Point(
|
||||||
ResizeNode(_selectedNode, deltaX, deltaY);
|
_initialNodePosition.X + deltaX,
|
||||||
}
|
_initialNodePosition.Y + deltaY
|
||||||
else
|
);
|
||||||
{
|
|
||||||
_selectedNode.Position = new PointF(
|
|
||||||
_initialNodePosition.X + deltaX,
|
|
||||||
_initialNodePosition.Y + deltaY
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
canvasView.Invalidate();
|
canvasView.Invalidate(); // Перерисовываем канву
|
||||||
}
|
}
|
||||||
|
// Завершение перетаскивания
|
||||||
else if (e.StatusType == GestureStatus.Completed)
|
else if (e.StatusType == GestureStatus.Completed)
|
||||||
{
|
{
|
||||||
_isResizing = false;
|
// Можно добавить логику на завершение перетаскивания, например, включить прокрутку
|
||||||
|
scrollView.IsEnabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResizeNode(GraphNode node, double deltaX, double deltaY)
|
|
||||||
{
|
|
||||||
const double minSize = 50.0;
|
|
||||||
|
|
||||||
if (_isResizing)
|
|
||||||
{
|
|
||||||
_selectedNode.Size = new Size(
|
|
||||||
Math.Max(minSize, _initialNodeSize.Width + deltaX),
|
|
||||||
Math.Max(minSize, _initialNodeSize.Height + deltaY)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsOnResizeHandle(GraphNode node, PointF point)
|
|
||||||
{
|
|
||||||
const float handleSize = 20f;
|
|
||||||
|
|
||||||
var resizeHandleRect = new RectF(
|
|
||||||
(float)(node.Position.X + node.Size.Width - handleSize),
|
|
||||||
(float)(node.Position.Y + node.Size.Height - handleSize),
|
|
||||||
handleSize, handleSize
|
|
||||||
);
|
|
||||||
|
|
||||||
return resizeHandleRect.Contains(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsPointInsideNode(PointF point, GraphNode node)
|
private bool IsPointInsideNode(PointF point, GraphNode node)
|
||||||
{
|
{
|
||||||
return point.X >= node.Position.X &&
|
return point.X >= node.Position.X &&
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue