Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> VirtualStringTree Drag&Drop 
V
    Опции темы
kami
Дата 2.3.2010, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(former @  2.3.2010,  22:04 Найти цитируемый пост)
Сначала OnAfterPost потом выход из OnDragDrop.

Вот и чудненько. Тогда всё сказанное из предыдущего поста - в силе.
PM MAIL WWW   Вверх
kami
Дата 3.3.2010, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(former @  2.3.2010,  19:32 Найти цитируемый пост)
Теперь ломаю голову над тем, как разрешить копировать нод только в ту ветку, где он должен находиться.

Не вижу проблемы.
Это реализуется в OnDragOver.
Примерный алгоритм (возможны варианты, код будет очень похож на OnDragDrop). Для простоты считаем, что выделить и перебросить несколько элементов сразу невозможно.

берем DropTargetNode и соответствующий ему TargetNodeData
берем SourceNodes[0] (если есть, конечно) и соответствующий ему SourceNodeData
Смотрим на Mode: TDropMode
Код

Если Mode=dmOnNode, то 
Accept:=(TargetNodeData.ElType='Пользователь') или 
    (TargetNodeData.ElType='КомпьютерЫ' и SourceNodeData.ElType='КомпьютеР') или 
    (TargetNodeData.ElType='ПравА' и SourceNodeData.ElType='ПравО').

Это гарантирует, что "внутрь" нода, над которым висит на данный момент курсор попадут только "свои" данные. Причем - если мы над "пользователем", то разрешаем всё. Если внутри какого-нибудь из списков (т.е. над элементом 3-го уровня) - то "так низзя".

Иначе (Mode<>dmOnNode) - пользователь пытается воткнуть новый нод между элементами. По логике это возможно только в том случае, если мы пытаемся воткнуться между элементами третьего уровня (т.е. компьютер - между компами, уже находящимися в списке "Компьютеры" этого пользователя, для прав - то же самое). Тут гораздо проще 
Код

Accept:=SourceNodeData.ElType=TargetNodeData.ElType. 
Всё, нет проблемы. smile 

Это сообщение отредактировал(а) kami - 3.3.2010, 00:51
PM MAIL WWW   Вверх
former
Дата 3.3.2010, 16:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 5
Всего: 17



kami, реализовал!

Переменные сделал глобальными.
Код

var
  MainForm: TMainForm;
  SourceNodes: TNodeArray;
  TargetNode: PVirtualNode;
  SourceNodeData: PUVSTRecord;
  TargetNodeData: PUVSTRecord;
  CopiedNodeData: PUVSTRecord;


OnDragDrop:
Код

procedure TMainForm.UsersVTDragDrop(Sender: TBaseVirtualTree; Source: TObject;
  DataObject: IDataObject; Formats: TFormatArray; Shift: TShiftState;
  Pt: TPoint; var Effect: Integer; Mode: TDropMode);
function GetNeededNode(DropNode: PVirtualNode; DropElType: TRecType): PVirtualNode;
begin
  Result := DropNode;
  while Sender.GetNodeLevel(Result) <> 0 do
    Result := Result.Parent;
  case DropElType of
    etPC: Result := Sender.GetFirstChild(Result);
    etRight:
      begin
        Result := Sender.GetFirstChild(Result);
        Result := Sender.GetNextSibling(Result);
      end;
    else
      Result := nil;
  end;
end;
begin
  Effect := DROPEFFECT_COPY;
  if not (Source is TBaseVirtualTree) then
    Exit;
  SourceNodes := TBaseVirtualTree(Source).GetSortedSelection(True);
  SourceNodeData := TBaseVirtualTree(Source).GetNodeData(SourceNodes[0]);
  if Assigned(SourceNodeData) then
  begin
    TargetNode := GetNeededNode(Sender.DropTargetNode, SourceNodeData.ElType);
    TargetNodeData:=Sender.GetNodeData(TargetNode);
    AddUserComp; //Запись данных в БД (см. ниже)
  end;
end;


OnDragOver:
Код

procedure TMainForm.UsersVTDragOver(Sender: TBaseVirtualTree;
  Source: TObject; Shift: TShiftState; State: TDragState; Pt: TPoint;
  Mode: TDropMode; var Effect: Integer; var Accept: Boolean);
var SourceNodesO: TNodeArray;
    TargetNodeO: PVirtualNode;
    SourceNodeDataO,TargetNodeDataO: PUVSTRecord;
begin
  if Source is TBaseVirtualTree then
  begin
    SourceNodesO := TBaseVirtualTree(Source).GetSortedSelection(True);
    SourceNodeDataO := TBaseVirtualTree(Source).GetNodeData(SourceNodesO[0]);
    if Assigned(SourceNodeDataO) then
    begin
      TargetNodeO:=Sender.DropTargetNode;
      TargetNodeDataO:=Sender.GetNodeData(TargetNodeO);
      if Assigned(TargetNodeDataO) then
      begin
        if Mode = dmOnNode then
        begin
          Accept:=(TargetNodeDataO.ElType = etUser) or
                ((TargetNodeDataO.ElType = etRootPC) and (SourceNodeDataO.ElType = etPC)) or
                ((TargetNodeDataO.ElType = etRootRights) and (SourceNodeDataO.ElType = etRight));

        end
        else Accept:=(SourceNodeDataO.ElType = TargetNodeDataO.ElType);
      end;
    end;
  end
  else Accept:=False;
end;


Запись данных в БД:
Код

procedure TMainForm.AddUserComp;
begin
  with UCompDataS do
  begin
    Append;
    FieldByName('SUSERID').AsInteger:=TargetNodeData.ElParentID;
    FieldByName('SCOMPUTERID').AsInteger:=SourceNodeData.ElID;
    Post;
  end;
end;


Добавление нода в дерево, если запись в БД успешна:
Код

procedure TMainForm.UCompDataSAfterPost(DataSet: TDataSet);
begin
  TargetNode := UsersVT.InsertNode(TargetNode, amAddChildLast);
  CopiedNodeData := UsersVT.GetNodeData(TargetNode);
  CopiedNodeData^ := SourceNodeData^;
end;


Вот только не понятно, что будет, если изменится количество нодов во втором уровне.


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
kami
Дата 3.3.2010, 19:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(former @  3.3.2010,  16:11 Найти цитируемый пост)
Вот только не понятно, что будет, если изменится количество нодов во втором уровне.

А ничего страшного не будет smile
Добавить новые типы в TElType и добавить "свои" условия в 
Цитата(former @  3.3.2010,  16:11 Найти цитируемый пост)
          
Accept:=(TargetNodeDataO.ElType = etUser) or  
                ((TargetNodeDataO.ElType = etRootPC) and (SourceNodeDataO.ElType = etPC)) or
                ((TargetNodeDataO.ElType = etRootRights) and (SourceNodeDataO.ElType = etRight));

 по аналогии с уже добавленными.
PM MAIL WWW   Вверх
former
Дата 3.3.2010, 19:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 5
Всего: 17



Я имел виду в функции GetNeededNode.
Вот на этом участке:
Код

case DropElType of
    etPC: Result := Sender.GetFirstChild(Result);
    etRight:
      begin
        Result := Sender.GetFirstChild(Result);
        Result := Sender.GetNextSibling(Result);
      end;
    else
      Result := nil;
  end;


Или с каждым новым нодом во 2-м уровне будет добавляться еще одна строка
Код

Result := Sender.GetNextSibling(Result);



--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
kami
Дата 3.3.2010, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(former @  3.3.2010,  19:15 Найти цитируемый пост)
Или с каждым новым нодом во 2-м уровне будет добавляться еще одна строка

Это было бы неоптимально, т.к. может измениться не только количество, но и порядок их следования.
Ну, давай подойдем к этой задаче так:

Код

function GetNeededNode(DropNode: PVirtualNode; DropElType: TRecType): PVirtualNode;
var
  RootType:TRecType; // тип "корневого" элемента - "КомпьютерЫ", "ПравА" и т.п.
  tmpNodeData:PVST...
begin
  Result := DropNode;
  // находим элемент "Пользователь"
  While Assigned(Result) do
    begin
      tmpNodeData:=Sender.GetNodeData(Result);
      if tmpNodeData.ElType=elUser then
        break;
      Result:=Result.Parent;
    end;
  if not Assigned(Result) then
    exit;
// определяемся с тем, какой из его под-элементов будем считать "корневым" для бросаемых данных.
// тут возможны варианты, например:
  case DropElType of
    etPC: RootType:=etRootPC;
    etRight: RootType:=etRootRight;
  end;
  // теперь мы имеем : в Result - пользователя, "внутрь" которого нужно добавить нод.  
  // в RootType - тип "дитя" пользователя, внутрь которого нужно добавить нод (гы, "Дом, который построил Джек")
  // пробегаем по дочерним элементам пользователя и ищем тот, который соответствует RootType
  Result:=Sender.GetFirstChild(Result);
  While Assigned(Result) do
    begin
      tmpNodeData:=Sender.GetNodeData(Result);
      if tmpNodeData.ElType=RootType then
        break
      else
        Result:=Sender.GetNextSibling(Result);
    end;
end;


Само собой, это только один из возможных вариантов работы. В нем, например, не предусмотрена возможность поиска не только в дочерних элементах первого уровня; мне не нравится то, что здесь пришлось использовать Case, что уже снижает универсальность... но дальше как-то не думается на сегодняшний день...
PM MAIL WWW   Вверх
former
Дата 4.3.2010, 10:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 5
Всего: 17



kami, не думал о том, что бы расширить статью Quadr0?


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
kami
Дата 4.3.2010, 13:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 23
Всего: 72



Цитата(former @  4.3.2010,  10:11 Найти цитируемый пост)
не думал о том, что бы расширить статью Quadr0?

Нет, а зачем? Там и так всё более чем расписано.
Единственное, что мог бы предложить в статью или околостатьевый материал - процедуру печати, которая не обрезает строки посередине, а действует почти так, как организована печать в Excel.
PM MAIL WWW   Вверх
former
Дата 4.3.2010, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 5
Всего: 17



Цитата(kami @  4.3.2010,  13:35 Найти цитируемый пост)
Единственное, что мог бы предложить в статью или околостатьевый материал - процедуру печати, которая не обрезает строки посередине, а действует почти так, как организована печать в Excel. 

Это было бы интересно! smile 


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Sed0Y
  Дата 3.4.2010, 18:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 48
Регистрация: 16.1.2009

Репутация: нет
Всего: нет



Добавте лучше статью - пример как строить дерево с БД к типа (многоуровневая):

Код

1 0
  2 1
  3 1
     4 3
     5 3
        6 5
  7 1
  8 1
9 0


а то я уже запарился - никак не могу придумать и найти - плз
PM MAIL ICQ   Вверх
former
Дата 4.4.2010, 20:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


MEMS Expert
***


Профиль
Группа: Завсегдатай
Сообщений: 1166
Регистрация: 1.3.2006
Где: Россия

Репутация: 5
Всего: 17



Цитата(Sed0Y @  3.4.2010,  18:48 Найти цитируемый пост)
Добавте лучше статью - пример как строить дерево с БД к типа (многоуровневая):

Sed0Y, а поиском в соответствующем разделе (БД) воспользоваться не пробовал?


--------------------
Достаточно снизить уровень мышления, чтобы иные почувствовали почву под ногами.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0569 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.