/* Copyright 2008 Edward Yakop. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. * * See the License for the specific language governing permissions and * limitations under the License. */ package org.qi4j.ide.plugin.idea.common.intentions; import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static org.qi4j.ide.plugin.idea.common.resource.Qi4jResourceBundle.message; /** * This class is based from {@code com.siyeh.ipp.base.Intention} * * @author edward.yakop@gmail.com */ public abstract class AbstractIntention extends PsiElementBaseIntentionAction { protected abstract boolean isIntentionValidFor( PsiElement element ); protected abstract String resourceBundlePrefixId(); /** * Implement this method to process intention. * * @param project The project in which the availability is checked. * @param editor The editor in which the intention will be invoked. * @param element The element under caret. */ protected abstract void processIntention( @NotNull Project project, @NotNull Editor editor, @NotNull PsiElement element ); public void invoke( @NotNull Project project, Editor editor, PsiFile file ) throws IncorrectOperationException { if( isFileReadOnly( project, file ) ) { return; } final PsiElement element = findMatchingElement( file, editor ); if( element == null ) { return; } processIntention( project, editor, element ); } protected static boolean isFileReadOnly( @NotNull Project project, @NotNull PsiFile file ) { VirtualFile virtualFile = file.getVirtualFile(); ReadonlyStatusHandler readonlyStatusHandler = ReadonlyStatusHandler.getInstance( project ); ReadonlyStatusHandler.OperationStatus operationStatus = readonlyStatusHandler.ensureFilesWritable( virtualFile ); return operationStatus.hasReadonlyFiles(); } @Nullable private PsiElement findMatchingElement( @NotNull PsiFile file, @NotNull Editor editor ) { CaretModel caretModel = editor.getCaretModel(); int position = caretModel.getOffset(); PsiElement element = file.findElementAt( position ); return findMatchingElement( element ); } @Nullable private PsiElement findMatchingElement( @Nullable PsiElement element ) { while( element != null ) { if( isIntentionValidFor( element ) ) { return element; } else { element = element.getParent(); if( element instanceof PsiFile ) { break; } } } return null; } @Override public boolean isAvailable( @NotNull Project project, Editor editor, @Nullable PsiElement element ) { return isIntentionValidFor( element ); } @NotNull public final String getFamilyName() { return message( resourceBundlePrefixId() + ".family.name" ); } @NotNull @Override public final String getText() { return message( resourceBundlePrefixId() + ".name" ); } }