コード例 #1
0
        /*
         * TODO
         * добавить случай, когда требуется scroll и, соответственно, поправить для
         * этого GetNearestCaretPosition, чтобы возвращалось что-то осмысленное, если точка за пределами текста
         * выделение влево и вправо - работает
         * выделение вверх и вниз - какая-то херь с индексами
         */
        private void mouse_select_do(Point mice_location)
        {
            int           ind      = 0;
            HitTextResult hit_test = text_area.HitTest(mice_location);

            ind = hit_test.CharacterIndex;
            long char_under_mice = ind + screen_first_char;

            if ((hit_test.HitTextType == HitTextType.Glyph) && (char_under_mice >= selection_first) && (char_under_mice < selection_last))
            {
                //выходим, если char под указателем уже выделен
                return;
            }

            //если char под указаьелем не выделен
            //смторим как он располагается относительно существующего выделения

            long pre_char = -1;

            //левый char выделен?
            pre_char = char_under_mice - 1;
            if ((pre_char >= selection_first) && (pre_char < selection_last))
            {
                //добавляем к выделению, char под указателем - конец выделения
                selection_set(selection_first, char_under_mice + 1);
                return;
            }

            //правый char выделен?
            pre_char = char_under_mice + 1;
            if ((pre_char >= selection_first) && (pre_char < selection_last))
            {
                //char под указателем - начало выделения
                selection_set(char_under_mice, selection_last);
                return;
            }

            //верхний char выделен?
            int   line_height = (int)Math.Ceiling(Font.GetHeight());
            Point pre_point   = new Point();

            pre_point.X = mice_location.X;
            pre_point.Y = mice_location.Y - line_height;
            HitTextResult neibo_hit = text_area.HitTest(pre_point);

            ind      = neibo_hit.CharacterIndex;
            pre_char = ind + screen_first_char;
            if ((hit_test.HitTextType == HitTextType.Glyph) && (pre_char >= selection_first) && (pre_char < selection_last))
            {
                //char под указателем - конец выделения
                selection_set(selection_first, char_under_mice + 1);
                return;
            }
            if ((hit_test.HitTextType == HitTextType.AfterText) && (pre_char >= selection_first) && (pre_char < selection_last))
            {
                //указатель ниже текста - прокрутка
                scroll_line_down();
                //теперь char под указателем - конец выделения
                hit_test        = text_area.HitTest(mice_location);
                char_under_mice = hit_test.CharacterIndex + screen_first_char;
                //если и после прокрутки под указатедем - пусто, выходим
                if (hit_test.HitTextType == HitTextType.Glyph)
                {
                    selection_set(selection_first, char_under_mice + 1);
                    return;
                }
                else
                {
                    return;
                }
            }

            //нижний char выдеден?
            pre_point.Y = mice_location.Y + line_height;
            text_area.GetNearestCaretPosition(pre_point, out ind);
            pre_char = ind + screen_first_char;
            if ((hit_test.HitTextType == HitTextType.Glyph) && (pre_char >= selection_first) && (pre_char < selection_last))
            {
                //char под указателем - начало выделения
                selection_set(char_under_mice, selection_last);
                return;
            }
            if ((hit_test.HitTextType == HitTextType.BeforeText) && (pre_char >= selection_first) && (pre_char < selection_last))
            {
                //нужна прокрутка вверх
                scroll_line_up();
                //теперь char под указателем - насчало выделения
                hit_test        = text_area.HitTest(mice_location);
                char_under_mice = hit_test.CharacterIndex + screen_first_char;
                //если и после прокрутки под указатедем - пусто, выходим
                if (hit_test.HitTextType == HitTextType.Glyph)
                {
                    selection_set(char_under_mice, selection_last);
                    return;
                }
                else
                {
                    return;
                }
            }

            //иначе начинаем новое выделение
            if (hit_test.HitTextType == HitTextType.Glyph)
            {
                selection_set(char_under_mice, char_under_mice + 1);
            }
        }
コード例 #2
0
        public HitTextResult HitTest(Point pt)
        {
            HitTextResult ret = new HitTextResult();

            if (LinesCount == 0)
            {
                ret.CharacterIndex       = -1;
                ret.CharacterIndexInLine = -1;
                ret.LineIndex            = -1;
                ret.HitTextType          = HitTextType.BeforeText;
                return(ret);
            }

            if (pt.Y < lines_info[0].ReferensePoint.Y)
            {
                ret.CharacterIndex       = -1;
                ret.CharacterIndexInLine = -1;
                ret.LineIndex            = -1;
                ret.HitTextType          = HitTextType.BeforeText;
                return(ret);
            }

            if (pt.Y > lines_info[LinesCount - 1].ReferensePoint.Y + lines_info[LinesCount - 1].Extent.Height)
            {
                ret.CharacterIndex       = -1;
                ret.CharacterIndexInLine = -1;
                ret.LineIndex            = -1;
                ret.HitTextType          = HitTextType.AfterText;
                return(ret);
            }

            int line_index = GetLineIndexFromPoint(pt);

            if (line_index == -1)
            {
                ret.CharacterIndex       = -1;
                ret.CharacterIndexInLine = -1;
                ret.LineIndex            = -1;
                ret.HitTextType          = HitTextType.Undefined;
                return(ret);
            }

            CharacterPositionInfo cpi = lines_info[line_index].GetCharacterIndexAtX(pt.X - lines_info[line_index].ReferensePoint.X);

            ret.CharacterIndex       = cpi.CharIndex + lines_info[line_index].CharFirst;
            ret.CharacterIndexInLine = cpi.CharIndex;
            ret.LineIndex            = line_index;

            switch (cpi.PositionType)
            {
            case CharacterPositionType.LeadingEdge:
            case CharacterPositionType.TrailingEdge:
            case CharacterPositionType.ClusterPart:
                ret.HitTextType = HitTextType.Glyph;
                break;

            case CharacterPositionType.BeforeBeginning:
                ret.HitTextType = HitTextType.BeforeOfLine;
                break;

            case CharacterPositionType.AfterEnd:
                ret.HitTextType = HitTextType.AfterOfLine;
                break;
            }
            return(ret);
        }