хз
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"
|
||||
Title="GraphPage">
|
||||
|
||||
<ContentPage.ToolbarItems>
|
||||
<ToolbarItem Text="Add Node" Clicked="OnAddNodeClicked"/>
|
||||
<ToolbarItem Text="Добавить дочернюю" Clicked="OnChildClicked"/>
|
||||
<ToolbarItem Text="Изменить размер" Clicked="OnResizeNodeClicked" />
|
||||
</ContentPage.ToolbarItems>
|
||||
|
||||
<ContentPage.Content>
|
||||
<AbsoluteLayout>
|
||||
<Grid RowDefinitions="*,Auto" Padding="10">
|
||||
<!-- Канва для рисования занимает верхнюю часть экрана -->
|
||||
<ScrollView x:Name="scrollView" Grid.Row="0" Orientation="Vertical">
|
||||
<AbsoluteLayout Grid.Row="0">
|
||||
<GraphicsView x:Name="canvasView"
|
||||
HeightRequest="800"
|
||||
WidthRequest="800" />
|
||||
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"
|
||||
IsVisible="False"
|
||||
BackgroundColor="White"
|
||||
TextColor="Black"
|
||||
FontSize="18" />
|
||||
</AbsoluteLayout>
|
||||
FontSize="18"
|
||||
Completed="OnTextEditorCompleted" />
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ namespace NotesDataAnalyst
|
|||
private readonly List<GraphNode> _nodes = new();
|
||||
private readonly List<GraphConnection> _connections = new();
|
||||
private GraphNode _selectedNode;
|
||||
private bool _isResizing = false;
|
||||
private bool _isScrollingBlocked = false;
|
||||
|
||||
|
||||
public GraphPage()
|
||||
{
|
||||
|
|
@ -27,6 +28,41 @@ namespace NotesDataAnalyst
|
|||
var tapGesture = new TapGestureRecognizer();
|
||||
tapGesture.Tapped += OnCanvasTapped;
|
||||
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)
|
||||
|
|
@ -61,16 +97,13 @@ namespace NotesDataAnalyst
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private async void OnAddNodeClicked(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
var newNode = new GraphNode
|
||||
{
|
||||
Text = "Новая нода",
|
||||
Position = new Point(100, 200),
|
||||
Size = new Size(100, 50),
|
||||
|
||||
};
|
||||
|
||||
_nodes.Add(newNode);
|
||||
|
|
@ -98,7 +131,6 @@ namespace NotesDataAnalyst
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnCanvasTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
var tapPosition = e.GetPosition((View)sender);
|
||||
|
|
@ -120,65 +152,35 @@ namespace NotesDataAnalyst
|
|||
{
|
||||
if (_selectedNode == null) return;
|
||||
|
||||
// Начало перетаскивания
|
||||
if (e.StatusType == GestureStatus.Started)
|
||||
{
|
||||
// Запоминаем начальную позицию касания и ноды
|
||||
_initialTouchPosition = new Point(e.TotalX, e.TotalY);
|
||||
_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)
|
||||
{
|
||||
var deltaX = (float)e.TotalX - _initialTouchPosition.X;
|
||||
var deltaY = (float)e.TotalY - _initialTouchPosition.Y;
|
||||
var deltaX = e.TotalX - _initialTouchPosition.X; // Разница с начальной точкой
|
||||
var deltaY = e.TotalY - _initialTouchPosition.Y;
|
||||
|
||||
if (_isResizing)
|
||||
{
|
||||
ResizeNode(_selectedNode, deltaX, deltaY);
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedNode.Position = new PointF(
|
||||
// Перемещаем ноду относительно её начальной позиции
|
||||
_selectedNode.Position = new Point(
|
||||
_initialNodePosition.X + deltaX,
|
||||
_initialNodePosition.Y + deltaY
|
||||
);
|
||||
}
|
||||
|
||||
canvasView.Invalidate();
|
||||
canvasView.Invalidate(); // Перерисовываем канву
|
||||
}
|
||||
// Завершение перетаскивания
|
||||
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)
|
||||
{
|
||||
return point.X >= node.Position.X &&
|
||||
|
|
|
|||
Loading…
Reference in a new issue